Openfeign
openfeign简介
Feign是声明性的web服务客户端。它使编写web服务客户端更加容易。要使用Feign,请创建一个接口并对其进行注释。它具有可插入的注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud添加了对Spring MVC注释的支持,并支持使用Spring Web中默认使用的同一HttpMessageConverters
。Spring Cloud集成了Ribbon和Eureka以在使用Feign时提供负载平衡的http客户端。
feign作用
feign旨在使编写Java Http客户端变的更加容易。
之前的学习中我们使用Ribbon + RestTemplate 对Http请求进行封装处理,形成了一套模板化的调用方法。但在实际开发中对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以,Feign在此基础上做了封装,来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它(以前是Dao接口上面标注Mapper注解,现在是一个微服务接口上标注一个Feign注解即可),便可按成对服务提供方的接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户的开发量。
使用feign
==用于消费者端==
创建maven项目
创建名为:cloud-consumer-order-feign-80 的项目。
修改pom文件
添加feign依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
创建applicaiton.yml
server:
port: 80
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
# defaultZone: http://localhost:7001/eureka
healthcheck:
enabled: true
spring:
application:
name: cloud-consumer-order-feign-80
创建启动类
添加@EnableFeignClients 注解,开启feign支持!
@SpringBootApplication
@EnableFeignClients
public class CloudConsumerOrderFeignApplication {
public static void main(String[] args) {
SpringApplication.run(CloudConsumerOrderFeignApplication.class,args);
}
}
编写业务类
通过一个接口封装需要调用的业务逻辑。
- 使用@FeignClient注解,value值为Eureka中注册的服务的名称。
- 添加服务提供者对应的方法及参数;
- 使用SpringMVC的Url映射注解和服务提供的URL进行对应。
@Component
@FeignClient(value = "CLOUD-PROVIDER-PAYMENT")
public interface PaymentFeignService {
@GetMapping("/payment/get/{id}")
public CommonResult getById(@PathVariable("id") Long id);
@GetMapping("/payment/feign/timeout")
public Object timeout();
}
测试
- 启动7001 Eureka服务端
- 启动7002 Eureka服务端
- 启动8001 支付服务提供
- 启动8002 支付服务提供
- 启动80 feign消费者模块
- 测试路径
测试结果如下:
feign超时控制
feign客户端默认只等待一秒钟,但是服务器端处理需要超过1秒钟,导致feign客户端不想等待了,直接返回错误;为了避免这种情况;有时候我们需要设置feign客户的超时控制。这需要在yml中开启。
错误模拟
添加模拟方法
我们在8001和8002服务提供端添加一个超1秒才能返回的方法;在之前的实例中PaymentController中:
@GetMapping("/feign/timeout")
@ResponseBody
public Object timeout(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return port;
}
添加消费端调用
@Component
@FeignClient(value = "CLOUD-PROVIDER-PAYMENT")
public interface PaymentFeignService {
@GetMapping("/payment/get/{id}")
public CommonResult getById(@PathVariable("id") Long id);
@GetMapping("/payment/feign/timeout")
public Object timeout();
}
添加Controller调用
@GetMapping("/payment/feign/timeout")
@ResponseBody
public Object timeout(){
return paymentFeignService.timeout();
}
测试结果
解决方案
在yml中配置相关超时参数,注意配置是没有语法自动提示的。
ribbon:
ConnectTimeout: 5000
ReadTimeout: 5000
feign日志增强
添加配置类
@Configuration
public class FeignConfig {
@Bean
public Logger.Level logLevel(){
return Logger.Level.FULL;
}
}
配置yml文件
logging:
level:
info.huzd.cloud.service.PaymentFeignService: debug
查看日志
2021-03-01 14:20:03.611 INFO 3382 --- [p-nio-80-exec-1] c.n.l.DynamicServerListLoadBalancer : DynamicServerListLoadBalancer for client CLOUD-PROVIDER-PAYMENT initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=CLOUD-PROVIDER-PAYMENT,current list of Servers=[130.30.3.224:8001, 130.30.3.224:8002],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone; Instance count:2; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0.0;]
},Server stats: [[Server:130.30.3.224:8002; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
, [Server:130.30.3.224:8001; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made: Thu Jan 01 08:00:00 CST 1970; Active Connections:0; total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0; stddev resp time:0.0]
]}ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@68ca0868
2021-03-01 14:20:03.664 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] <--- HTTP/1.1 200 (170ms)
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] connection: keep-alive
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] content-type: application/json
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] date: Mon, 01 Mar 2021 06:20:03 GMT
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] keep-alive: timeout=60
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] transfer-encoding: chunked
2021-03-01 14:20:03.665 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById]
2021-03-01 14:20:03.666 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] {"code":200,"message":"查询成功(服务端口:8001)","object":{"id":1,"serial":"101010101010101"}}
2021-03-01 14:20:03.666 DEBUG 3382 --- [p-nio-80-exec-1] i.h.cloud.service.PaymentFeignService : [PaymentFeignService#getById] <--- END HTTP (103-byte body)
2021-03-01 14:20:04.609 INFO 3382 --- [erListUpdater-1] c.netflix.config.ChainedDynamicProperty : Flipping property: CLOUD-PROVIDER-PAYMENT.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647
以上的第一步也可以用过一个配置实现:
feign:
client:
config:
default:
connectTimeout: 5000 #效果等同ribbon.ConnectTimeout
readTimeout: 5000 #效果等同ribbon.readTimeout
loggerLevel: full # 可以取代第一步
本文由 huzd 创作,采用 知识共享署名4.0 国际许可协议进行许可本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名最后编辑时间
为:
2021/03/01 14:38