赞
踩
目录
2.在order-service(发起远程调用的微服务)的启动类添加注解开启Feign的功能
1.方式一:给消费者的FeignClient和提供者的controller定义统一的父接口作为标准。
2.方式二(推荐):将FeignClient抽取为独立模块,并且把接口有关的POJO(实体类)、默认的Feign配置都放到这个模块中,提供给所有消费者使用
以往我们是通过 RestTemplate 发起远程调用,如下
存在问题如下:
Feign 是一个声明式的 http 客户端,其作用就是用来把我们解决上述问题的~
主要分为以下步骤:
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
注意:由于SpringCloud Feign高版本(例如 2020.1.0)不使用Ribbon而是使用spring-cloud-loadbalancer,所以需要引用spring-cloud-loadbalancer或者降版本
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-loadbalancer</artifactId>
- </dependency>
-
- <dependency>
- <groupId>com.github.ben-manes.caffeine</groupId>
- <artifactId>caffeine</artifactId>
- </dependency>
主要是基于SpringMVC的注解来声明远程调用的信息,比如:
- import cn.itcast.order.pojo.User;
- import org.springframework.cloud.openfeign.FeignClient;
- import org.springframework.stereotype.Component;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.PathVariable;
-
- @Component
- @FeignClient("userservice")
- public interface UserClients {
-
- @GetMapping("/user/{id}")
- User findById(@PathVariable("id") Long id);
-
- }
如果是高版本的 SpringCloud,那么就需要使用 SpringCloud LoadBalencer 做负载均衡(也比较建议).
具体的添加@LoadBalancerClient注解:在调用服务的Service类上添加@LoadBalancerClient注解,并指定服务名。这样,负载均衡器将根据配置的属性来选择合适的服务实例进行调用。例如:
如下:
- @FeignClient(value = "service-name", configuration = LoadBalancerClientConfiguration.class)
- public interface MyService {
- @LoadBalanced //启用负载均衡
- @GetMapping("/endpoint")
- String getEndpointData();
- }
用 Feign 来代替 RestTemplate 是不是十分优雅~
Ps:OpenFeign早期版本(例如 Hoxton.SR6 )要求服务提供方在1秒内处理业务逻辑并返回响应。如果超过1秒没有返回,OpenFeign会直接报错,不会等待服务执行。随着版本的更新,OpenFeign已经对此做出了调整或优化(例如 2021.0.1)。
超时报错如下:
修改超时时间:
a)在远程调用方的 application.yml 中配置,指定某个服务提供方的调用超时时间
- feign:
- client:
- config:
- product: # 服务名
- connect-timeout: 5000 # 配置指定服务连接超时时间
- read-timeout: 5000 # 配置指定服务等待超时时间
b)在远程调用方的 application.yml 中配置,指定所有服务提供方的调用超时时间
- feign:
- client:
- config:
- default: # 所有服务
- connect-timeout: 5000 # 配置指定服务连接超时时间
- read-timeout: 5000 # 配置指定服务等待超时时间
OpenFeign 为了更好的方便在开发过程中检测 openfeign 数据传递 和 响应处理,在设计时提供了日志功能. 默认 openfeign 日志功能需要手动开启的.
日志级别有以下 4 种:
配置Feign日志有以下两种方式:
a)开启 openfeign 日志展示
- #开启 openfeign 日志
- logging:
- level:
- org: # 这里是 feign 客户端接口包路径
- example:
- feign: debug
b)全局生效
- feign:
- client:
- config:
- default: # 所有服务生效
- logger-level: FULL
c)局部生效
- feign:
- client:
- config:
- user: # 如果是写服务名称,则是针对某个微服务的配置
- logger-level: FULL
d)FULL 级别日志展示如下
首先需要声明一个 Bean,如下
- public class FeignClientConfiguration {
- @Bean
- public Logger.Level feignLogLevel(){
- return Logger.Level.BASIC; //一般使用 BASIC 级别,因为太多的日志信息影响效率
- }
- }
情况一:如果是全局配置,则把它放到@EnableFeignClients这个注解中:
@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)
情况二:如果是局部配置,则把它放到@FeignClient这个注解中:
@FeignClient(value = "userservice", configuration = FeignClientConfiguration.class)
Feign 的底层客户端实现:
因此优化Feign的性能主要包括:
因此使用 HttpClient 或 OKHttp 代替 URLConnection
- <!--httpClient的依赖 -->
- <dependency>
- <groupId>io.github.openfeign</groupId>
- <artifactId>feign-httpclient</artifactId>
- </dependency>
- feign:
- client:
- config:
- default: # default全局的配置
- loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
- httpclient:
- enabled: true # 开启feign对HttpClient的支持
- max-connections: 200 # 最大的连接数
- max-connections-per-route: 50 # 每个路径的最大连接数
仔细观察我们可以发现, Feign 发起远程调用的接口和接收远程调用请求的 controller 层实现代码是一样的,因此,我们我可以把他们的共性提取出来,写成一个公开的接口,将来我们使用的时候只需要继承这个接口即可,如下图
但这种方式存在一定的问题,以下是官方提出的问题:
也就是说
具体步骤:
1.首先创建一个module,命名为feign-api,然后引入feign的starter依赖
- <!--feign 客户端依赖-->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-openfeign</artifactId>
- </dependency>
2.将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中
3.在order-service中引入feign-api的依赖
4.修改order-service中的所有与上述三个组件有关的import部分,改成导入feign-api中的包
5.重启测试
这个时候你重启项目,项目必然会报以下错误
为什么 UserClients 没有对应的对象呢?
UserClients 之前有对象是因为扫描到 @FeignClient 注解注入了对象 ,而现在 order-service 扫描包的范围是启动类下的包,但由于我们刚刚把 UserClients 挪到了 feign-api 这个 Module 中,因此,扫描不到该注解,无法注入对象。
总而言之:当定义的FeignClient不在SpringBootApplication的扫描包范围时,这些FeignClient无法使用。
有以下两种解决方式:
方式一:指定FeignClient所在包
@EnableFeignClients(basePackages = "cn.itcast.feign.clients")
这种方式会将指定包下的所有东西都拿过来。
方式二(推荐):指定FeignClient字节码
@EnableFeignClients(clients = {UserClient.class})
这种方式是精准打击,只拿指定的类,效率上更推荐使用,用哪个,就指定哪个.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。