Feign是一个声明式WebService客户端。使用Feign能让编写Web Service客户端更加简单。
他的使用方法是 定义一个服务接口,然后在上面添加注解。 Feign也支持可拔插式的编码器和解码器。Feign可以与Eureka和Ribbon组合使用以支持负载均衡
Feign旨在使编写java http客户端变得更简单。在使用Ribbon+RestTemplate时,利用RestTemplate对http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往在一个接口会被多处调用,所以通常都会针对每个微服务自行封装一些客户端来包装这些依赖服务的调用。 所以,Feign在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,我们只需要创建一个接口并使用注解的方式来配置它 ,即可完成对服务提供方接口绑定,简化了使用Spring Cloud Ribbon时,自动封装服务调用客户端的开发量。
接口加注解调用
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
cn.nwnu.springcloud
cloud-api-commons
${project.version}
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.springframework.boot
spring-boot-devtools
runtime
true
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-test
test
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableFeignClients //激活OpenFeign
public class OrderFeignMain80 {
public static void main(String args[]){
SpringApplication.run(OrderFeignMain80.class, args);
}
}
@FeignClient
value是注册进eureka的服务名称
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentFeignService {
/**
* 相当于RestTemplate调用微服务http://CLOUD-PAYMENT-SERVICE/payment/get/{id}
* openFeign做了封装,简化开发,在controller直接调用PaymentFeignService即可
* @param id
* @return
*/
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id);
}
@RestController
@Slf4j
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id){
//直接调用PaymentFeignService
return paymentFeignService.getPaymentById(id);
}
}
OpenFeign默认等待1s,超过1s就报错timeout
/**
* 演示超时
* @return
*/
@GetMapping(value = "/feign/timeout")
public String paymentFeignTimeout(){
//暂停几秒钟线程
try{
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return serverPort;
}
@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout();
/**
* 演示超时
* @return
*/
@GetMapping(value = "/consumer/payment/feign/timeout")
public String paymentFeignTimeout(){
return paymentFeignService.paymentFeignTimeout();
}
通过上述步骤,服务自测通过,但是通过客户端访问是,报错timeout
默认Feign客户端只等待一秒,但是服务端处理超过1秒,导致feign客户端不想等待了,直接返回报错,为了避免这样的错误,我们需要设置Feign客户端超时控制
#设置Feign客户端超时时间(OpenFeign默认支持Ribbon
ribbon:
# 指的是建立连接所用的时间,适用于网络正常的情况下,两端连接所用时间
ReadTimeout: 5000
# 指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
feign提供了日志打印功能,我们可以通过配置来调整日志级别,从而了解Feign中http请求的细节,说白了就是***对Feign接口的调用进行监控和输出***
配置日志bean
package cn.nwnu.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
/**
* 开启最详细的日志
* @return
*/
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
yml文件需要开启日志的Feign客户端
logging:
level:
# feign日志以什么级别监控哪个接口
cn.nwnu.springcloud.services.PaymentFeignService: debug
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] <--- HTTP/1.1 200 (325ms)
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] connection: keep-alive
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] content-type: application/json
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] date: Tue, 17 Mar 2020 01:59:23 GMT
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] keep-alive: timeout=60
2020-03-17 09:59:23.101 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] transfer-encoding: chunked
2020-03-17 09:59:23.102 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById]
2020-03-17 09:59:23.103 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] {"code":200,"message":"成功8001","data":{"id":31,"serial":"dfsgsfhsgf"}}
2020-03-17 09:59:23.103 DEBUG 4000 --- [p-nio-80-exec-1] c.n.s.services.PaymentFeignService : [PaymentFeignService#getPaymentById] <--- END HTTP (74-byte body)
2020-03-17 09:59:23.994 INFO 4000 --- [erListUpdater-0] c.netflix.config.ChainedDynamicProperty : Flipping property: CLOUD-PAYMENT-SERVICE.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647