Feign是Spring Cloud组件中的一个轻量级RESTful的HTTP服务客户端Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。
Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务Feign本身不支持Spring MVC的注解,它有一套自己的注解
OpenFeign是Spring Cloud 在Feign的基础上支持了Spring MVC的注解,如@RequesMapping等,是一个轻量级的Http封装工具对象,大大简化了Http请求,使得我们对服务的调用转换成了对本地接口方法的调用。
OpenFeign 的 @FeignClient 可以解析SpringMVC的 @RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
创建Feign接口
@FeignClient(value = "xx-template-service")//value = "xx-template-service"指定服务的名字
public interface DriverFeign {
/**
* demo feign 接口
*/
@PutMapping(value = "/driver/status")
Driver status(String id, Integer status);
}
Feign会通过动态代理,帮我们生成实现类。
注解@FeignClient声明Feign的客户端,注解value指明服务名称接口定义的方法,采用SpringMVC的注解。Feign会根据注解帮我们生成URL地址
FeignClient 注解参数
注意事项
启用OpenFeign
我们需要在服务的启动类上开启 OpenFeign ,只需要在 **Application 启动类上添加 @EnableFeignClients即可。
logging:
level:
xx.template.cloud.web.service.feign.ServiceServiceFeign: debug
通过loggin.level.xx=debug来设置日志级别。然而这个对Feign客户端不会产生效果。因为@FeignClient注解修饰的客户端在被代理时,都会创建一个新的Feign.Logger实例。我们需要额外指定这个日志的级别才可以。
/**
* feign 日志级别配置
* @return
*/
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
或者在配置文件中配置
feign:
client:
config:
# 全局配置
default:
loggerLevel: full
Feign支持4种级别:
NONE:不记录任何日志,默认值
BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
HEADERS:在BASIC基础上,额外记录了请求和响应的头信息
FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据
用户在网络请求过程中,如果网络不佳、传输数据过大,会造成体验差的问题,我们需要将传输数据压缩提升体验。SpringCloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
在客户端中配置数据压缩
feign:
compression:
request:
enabled: true # 开启请求压缩
response:
enabled: true # 开启响应压缩
也可以对请求的数据类型,以及触发压缩的大小下限进行设置
feign:
compression:
request:
enabled: true # 开启请求压缩
mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
min-request-size: 2048 # 设置触发压缩的大小下限
#以上数据类型,压缩大小下限均为默认值
response:
enabled: true # 开启响应压缩
首先在配置文件中配置如下,开启熔断降级
feign.hystrix.enabled=true
Feign 定义降级方法
feign接口定义
/**
* FeignClient 注解的 fallback 属性指定降级类
*/
@FeignClient(name = "xx-template-cloud-service", fallback = ServiceServiceFeignFallBack.class)
public interface ServiceServiceFeign {@GetMapping("/order/getOrder")
Result getOrder(String id);
}
feign接口降级方法定义
@Slf4j
@Component
class ServiceServiceFeignFallBack implements ServiceServiceFeign {@Override
public Result getOrder(String id) {
log.error("Feign接口熔断 熔断方式:ServiceServiceFeignFallBack");
return Result.error("500", "Feign接口熔断");
}
}
Feign 定义降级工厂
feign接口定义
/**
* FeignClient 注解的 fallback 属性指定降级类
*/
@FeignClient(name = "xx-template-cloud-service", fallback = UserCenterFeignClientFallbackFactory.class)
public interface ServiceServiceFeign {@GetMapping("/order/getOrder")
Result getOrder(String id);
}
feign接口降级工厂定义
@Component
@Slf4j
class UserCenterFeignClientFallbackFactory implements FallbackFactory<ServiceServiceFeign> {@Override
public ServiceServiceFeign create(Throwable cause) {
return new ServiceServiceFeign() {
@Override
public Result getOrder(String id) {
log.error("Feign接口熔断,熔断方式:UserCenterFeignClientFallbackFactory");
return Result.error("500", "Feign接口熔断");
}
};
}
}
OpenFeign默认使用jdk自带的HttpURLConnection,我们知道HttpURLConnection没有连接池、性能和效率比较低,如果采用默认,很可能会遇到性能问题导致系统故障
可以采用Apache HttpClient
注意feign-httpclient的版本,如果和Open Feign 不兼容可能会报original request is required异常
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
<version>10.10.1</version>
</dependency>
feign.httpclient.enabled=true
也可以采用OkHttpClient
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
<version>10.2.0</version>
</dependency>
feign.okhttp.enabled=true
ribbon中的Http Client
通过OpenFeign作为注册中心的客户端时,默认使用Ribbon做负载均衡,Ribbon默认也是用jdk自带的HttpURLConnection,需要给Ribbon也设置一个Http client,比如使用okhttp,在properties文件中增加下面配置
ribbon.okhttp.enabled=true
OpenFeign可以设置超时时间,简单粗暴,设置一个全局的超时时间。如果不配置超时时间,默认是连接超时10s,读超时60s。
feign.client.config.default.connectTimeout=2000
feign.client.config.default.readTimeout=60000
但是如果某个服务的并发量很高,服务的超时时间过长会导致占用大量连接资源,导致系统崩溃,要防止这样的故障发生,最好的做法就是给服务单独设置超时时间。
当然,如果开启熔断后,不配置hystrix和ribbon的超时时间,那么Hystrix与ribbon的默认请求超时时间都是1秒,建议配置Hystrix的超时时间要大于ribbon的超时时间,否则会在接口调用还未完成的时候直接进入回调方法。
# 开启熔断
feign.hystrix.enabled: true
上文所述,对单个服务设置超时时间。
feign.client.config.serviceA.connectTimeout=2000
feign.client.config.serviceA.readTimeout=60000
但是如果serviceA中有多个接口,其中X接口又调用serviceB的Feign接口,为了保证X接口请求不被单服务超时时间影响,需要单独对X接口设置超时时间。
几个组件的关系
hystrix+ribbon。hystrix在最外层,然后再到Ribbon,最后里面的是http请求。所以说。hystrix的熔断时间必须大于ribbon的 ( ConnectTimeout + ReadTimeout )。而如果ribbon开启了重试机制,还需要乘以对应的重试次数(注意这里的重试可以是ribbon的重试也可能是feign的重试),保证在Ribbon里的请求还没结束时,Hystrix的熔断时间不会超时。
我用的spring cloud版本是Hoxton.SR8
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR8</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
原因是Feign 在spring cloud Hoxton.M2版本之后,不再使用ribbon,所以我们在pom文件中还需要导入loadbalancer依赖,并排除掉nacos的ribbon依赖。
<!--nacos-discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2021.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
并在配置文件中添加
spring.cloud.loadbalancer.ribbon.enabled: false
手机扫一扫
移动阅读更方便
你可能感兴趣的文章