一、概述
OpenFeign能干什么?
前面在使用SpringCloud LoadBalancer+RestTemplate时,利用RestTemplate对http请求的封装处理形成了一套模版化的调用方法。
但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,OpenFeign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。
在OpenFeign的实现下,我们只需创建一个接口并使用注解的方式来配置它(在一个微服务接口上面标注一个@FeignClient注解即可),即可完成对服务提供方的接口绑定,统一对外暴露可以被调用的接口方法,大大简化和降低了调用客户端的开发量,也即由服务提供者给出调用接口清单,消费者直接通过OpenFeign调用即可。
OpenFeign同时还集成SpringCloud LoadBalancer,可以在使用OpenFeign时提供Http客户端的负载均衡,也可以集成阿里巴巴Sentinel来提供熔断、降级等功能。
而与SpringCloud LoadBalancer不同的是,通过OpenFeign只需要定义服务绑定接口且以声明式的方法,优雅而简单的实现了服务调用。
OpenFeign是SpringCloud在Feign的基础上支持了SpringMVC的注解,如@RequstMapping等等。
OpenFeign的@FeignClient可用解析SPringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
二、简单入门
<!--openfeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>@SpringBootApplication @EnableDiscoveryClient //该注解用于向使用consul为注册中心时注册服务 @EnableFeignClients//启用feign客户端,定义服务+绑定接口,以声明式的方法优雅而简单的实现服务调用 public class MainOpenFeign80{ public static void main(String[] args){ SpringApplication.run(MainOpenFeign80.class,args); } }生产者的微服务:
@RestController public class PayController { @PostMapping("/pay/add") public String addPay(@RequestBody Pay pay){ return "新增一条支付信息成功"; } @GetMapping("/pay/get/{id}") public String getPayInfo(@PathVariable("id") Integer id){ return "按照主键记录查询支付流水信息"; } }对应的微服务接口:
//openfeign天然支持负载均衡演示 @FeignClient(value = "cloud-payment-service") public interface PayFeignApi{ //新增一条支付相关流水记录 @PostMapping("/pay/add") public String addPay(@RequestBody Pay pay); //按照主键记录查询支付流水信息 @GetMapping("/pay/get/{id}") public String getPayInfo(@PathVariable("id") Integer id); }消费者服务:
@RestController public class OrderController{ @Resource private PayFeignApi payFeignApi; @PostMapping(value = "/feign/pay/add") public String addPay(@RequestBody Pay pay){ String str = payFeignApi.addPay(pay); return str; } @GetMapping(value = "/feign/pay/get/{id}") public ResultData getPayInfo(@PathVariable("id") Integer id){ String str = payFeignApi.getPayInfo(id); return str; }三、高级特性
1、超时控制
在Spring Cloud微服务架构中,大部分公司都是利用OpenFeign进行服务间的调用,而比较简单的业务使用默认配置是不会有多大问题的,但是如果是业务比较复杂,服务要进行比较繁杂的业务计算,那后台很有可能会出现Read Timeout这个异常,因此定制化配置超时时间就有必要了。
#全局配置 spring: cloud: openfeign: client: config: default: #连接超时时间 connectTimeout: 3000 #读取超时时间 readTimeout: 3000 #单独对某个微服务进行设置 cloud-payment-service: #连接超时时间 connectTimeout: 20000 #读取超时时间 readTimeout: 200002、重试机制
//OpenFeign重试设置 @Configuration public class FeignConfig{ @Bean public Retryer myRetryer(){ //return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的 //最大请求次数为3(1+2),初始间隔时间为100ms,重试间最大间隔时间为1s return new Retryer.Default(100,1,3); } }3、默认HttpClient修改
OpenFeign中HttpClient如果不做特殊配置,OpenFeign默认使用JDK自带的HttpURLConnection发送HTTP请求,由于默认HttpURLConnection没有连接池、性能和效率比较低,如果采用默认,性能上不是最好的,所以加到最大。
<!-- httpclient5--> <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.3</version> </dependency> <!-- feign-hc5--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-hc5</artifactId> <version>13.1</version> </dependency>@Configuration public class FeignConfig{ @Bean public Retryer myRetryer(){ return Retryer.NEVER_RETRY; //Feign默认配置是不走重试策略的 } }openfeign: httpclient: hc5: enabled: true4、请求/响应压缩
对请求和响应进行GZIP压缩:
Spring Cloud OpenFeign支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。
通过下面的两个参数设置,就能开启请求与相应的压缩功能:
spring.cloud.openfeign.compression.request.enabled=true
spring.cloud.openfeign.compression.response.enabled=true
细粒度化设置:
对请求压缩做一些更细致的设置,比如下面的配置内容指定压缩的请求数据类型并设置了请求压缩的大小下限,只有超过这个大小的请求才会进行压缩:
- spring.cloud.openfeign.compression.request.enabled=true
- spring.cloud.openfeign.compression.request.mime-types=text/xml,application/xml,application/json #触发压缩数据类型
- spring.cloud.openfeign.compression.request.min-request-size=2048 #最小触发压缩的大小
openfeign: compression: request: enabled: true min-request-size: 2048 #最小触发压缩的大小 mime-types: text/xml,application/xml,application/json #触发压缩数据类型 response: enabled: true5、日志打印
Feign 提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解 Feign 中 Http 请求的细节,说白了就是对Feign接口的调用情况进行监控和输出。
- NONE:默认的,不显示任何日志;
- BASIC:仅记录请求方法、URL、响应状态码及执行时间;
- HEADERS:除了 BASIC 中定义的信息之外,还有请求和响应的头信息;
- FULL:除了 HEADERS 中定义的信息之外,还有请求和响应的正文及元数据。
@Configuration public class FeignConfig{ @Bean public Retryer myRetryer(){ return Retryer.NEVER_RETRY; //默认 } //配置日志级别 @Bean Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }# feign日志以什么级别监控哪个接口 logging: level: com: atguigu: cloud: apis: PayFeignApi: debug