前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringCloud实战: Feign<上>

SpringCloud实战: Feign<上>

作者头像
田维常
发布2019-07-16 10:58:09
4260
发布2019-07-16 10:58:09
举报

概述

很多使用spring cloud 主要是注册中心,动态配置中心,服务调用,负载均衡,熔断,网关。Feign是一个声明式的Web Service客户端,整合了注解,所以使用起来比较方便,通过它调用HTTP请求访问远程服务,就像访问本地方法一样简单开发者完全无感知。

申明式:接口声明、Annotation 驱动

Web 服务:HTTP 的方式作为通讯协议

客户端:用于服务调用的存根

Feign:原生并不是 Spring Web MVC的实现,基于JAX-RS(Java REST 规范)实现。Spring Cloud 封装了Feign ,使其支持 Spring Web MVC。

RestTemplate、HttpMessageConverter、RestTemplate以及 Spring Web MVC 可以显示地自定义 HttpMessageConverter实现。

场景

假设,有一个Java 接口 UserService, Feign 可以将其声明它是以 HTTP 方式调用的。

注册中心(Eureka Server):服务发现和注册

关于Eureka请阅读:Spring Cloud Netflix Eureka学习

a. 应用名称:spring-cloud-eureka-server

b. 服务端口:66666

application.properties配置如下:

代码语言:javascript
复制
spring.application.name = spring-cloud-eureka-server
## Eureka 服务器端口
server.port =66666
### 取消服务器自我注册
eureka.client.register-with-eureka=false
### 注册中心的服务器,没有必要再去检索服务
eureka.client.fetch-registry = false
management.security.enabled = false

Feign 声明接口(契约):定义一种 Java 强类型接口

模块:user-api

UserService.java

代码语言:javascript
复制
package com.lawt.spring.cloud.feign.api.service;
import com.lawt.spring.cloud.feign.api.domain.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.Collection;

//{@link User} 服务
@FeignClient(value = "user-service") // 服务提供方应用的名称
public interface UserService {
    //保存
    @PostMapping(value = "/user/save")
    boolean save(@RequestBody User user);
    // 查找所有的服务
    @GetMapping(value = "/user/find/all")
    Collection<Person> findAll();
}

Feign 客户(服务消费)端:调用Feign 申明接口

应用名称:user-client

pom中依赖:user-api

创建UserClientController.java

代码语言:javascript
复制
package com.lawt.spring.cloud.feign.client.web.controller;
import com.lawt.spring.cloud.feign.api.domain.User;
import com.lawt.spring.cloud.feign.api.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Collection;

/**
 * {@link UserClientController} 实现 {@link UserService}
 */
@RestController
public class UserClientController implements UserService {
    private final UserService userService;
    @Autowired
    public UserClientController(UserService userService) {
        this.userService= userService;
    }
    @Override
    public boolean save(@RequestBody User user) {
        return userService.save(user);
    }
    @Override
    public Collection<User> findAll() {
        return userService.findAll();
    }
}

启动类:UserClientApplication.java

代码语言:javascript
复制
package com.lawt.spring.cloud.feign.client;

import com.lawt.spring.cloud.feign.api.service.UserService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

/**
 * User Client 应用程序 
 */
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(clients = UserService.class)
public class UserClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserClientApplication.class,args);
    }
}

client端配置 application.properties

代码语言:javascript
复制
spring.application.name = user-client
server.port = 8080
## Eureka Server 服务 URL,用于客户端注册
eureka.client.serviceUrl.defaultZone=http://localhost:66666/eureka
management.security.enabled = false

Feign 服务(服务提供)端:不一定强制实现 Feign 申明接口

应用名称:user-service

pom中依赖:user-api

创建 UserServiceController

代码语言:javascript
复制
package com.lawt.spring.cloud.feign.person.service.provider.web.controller;
import com.lawt.spring.cloud.feign.api.domain.User;
import com.lawt.spring.cloud.feign.api.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
 * {@link  UserService} 提供者控制器(可选实现{@link UserService})
 */
@RestController
public class UserServiceProviderController {
    private final Map<Long, User> users = new ConcurrentHashMap<>();
    /**
     * 保存
     * @param user{@link  User}
     * @return 如果成功,<code>true</code>
     */
    @PostMapping(value = "/user/save")
    public boolean saveUser(@RequestBody User user) {
        return users.put(user.getId(), user) == null;
    }
    //查找所有的服务
    @GetMapping(value = "/user/find/all")
    public Collection<User> findAllUsers() {
        return users.values();
    }
}

服务端启动类:UserProviderApplication .java

代码语言:javascript
复制
package com.lawt.spring.cloud.feign.person.service.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
/**
 * {@UserService} 提供者应用
 */
@SpringBootApplication
@EnableEurekaClient
public class UserProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserProviderApplication .class,args);
    }
}

服务端配置 application.properties

代码语言:javascript
复制
## 提供方的应用名称需要和 @FeignClient 声明对应
spring.application.name = user-service
## 提供方端口 9090
server.port = 9090
## Eureka Server 服务 URL,用于客户端注册
eureka.client.serviceUrl.defaultZone=http://localhost:66666/eureka
## 关闭管理安全
management.security.enabled = false

Feign 客户(服务消费)端、Feign 服务(服务提供)端 以及 Feign 声明接口(契约) 存放在同一个工程目录。

调用顺序

PostMan -> user-client -> user-service

use-api 定义了 @FeignClients(value="user-service") , user-service 实际是一个服务器提供方的应用名称。

user-client 和 user-service 两个应用注册到了Eureka Server

user-client 可以感知 user-service 应用存在的,并且 Spring Cloud 帮助解析 UserService 中声明的应用名称:“user-service”,因此 user-client 在调用 `UserService `服务时,实际就路由到 user-service 的 URL

Feign原理

我们首先会添加@EnableFeignClients注解开启对 FeignClient扫描加载处理,扫描后会注入到SpringIOC容器,当定义的feign接口方法被调用时,通过JDK代理的方式,生成具体的RequestTemplate,RequestTemplate生成Request,交给URLConnection处理,并结合LoadBalanceClient与Ribbon,以负载均衡的方式发起服务间的调用。

Feign特性

整合了Hystrix,支持fallback容错降级

整合了Ribbon,直接请求的负载均衡

支持HTTP请求和响应的压缩

使用OkHttp替换原生URLConnection,提高效率

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档