一、OpenFeign介绍
OpenFeign是Netfix开发的一款声明式,模板化的Http服务调用客户端。使用在服务调用者工程端。OpenFeign的负载均衡也为客户端负载均衡。一下简称Feign。
Feign 与 OpenFeign的区别:Feign是Springcloud组件中的一个轻量级Restful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务;OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
二、基本配置使用
1,添加openfen依赖:
org.springframework.cloud
spring-cloud-starter-openfeign
2,启动类添加激活OpenFeign注解@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
3,编写http远程调用接口类
@FeignClient(name="CLOUD-PAYMENT-SERVICE")
public interface ProductFeignClient {
@RequestMapping(value="/payment/get/{id}",method = RequestMethod.GET)
CommonResult getPayment(@PathVariable("id") Long id);
@GetMapping("/payment/get/timeout")
CommonResult getPaymentTimeout();
}
注意接口类需要添加@FeignClient(name="CLOUD-PAYMENT-SERVICE") 注解。注解中name值为服务提供者服务名称。 接口中方法需要添加SpringMVC注解来声明调用的远程方法路径。方法参数要与远程接口提供方参数一致。
4,在Controller中注入并使用调用
@RestController
public class OrderController {
@Autowired
private ProductFeignClient productFeignClient;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPayment(@PathVariable("id") Long id){
return productFeignClient.getPayment(id);
}
@GetMapping("/consumer/payment/get/timeout")
public CommonResult getPaymentTimeout(){
return productFeignClient.getPaymentTimeout();
}
}
在Controller中使用比较简单,注解注入接口类,然后使用接口类方法直接调用即可。和我们之前单机版的Controller调用Service结构比较一致。
测试验证:我们启动Eureka注册中心,并分别启动服务提供者工程2个,和当前feign工程。访问feign工程的controller中方法地址,相关展示信息如下:
三、负载均衡配置
由于OpenFeign对ribbon的支持所以,OpenFeign的负载均衡也是客户端负载均衡,配置方式和ribbon的也一样。最顶级的为服务名称。默认的为轮询策略,如下配置的为随机策略。
CLOUD-PAYMENT-SERVICE:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
负载均衡测试:我们启动两个生产者工程端口分别为8002 和 8003,并将调用执行的节点端口进行返回。首先不配置负载均衡相关配置进行测试
如下为配置了随机请求后的访问效果。
四、超时及日志级别配置
在开发或这运行时,如果需要看到Feign的请求过程可以通过Feign的日志进行查看。默认情况下Feign日志没有开启。如果需要开启,则需要在yml中添加如下feign.client.config中设置即可。
其中loggerLevel中枚举包含:
超时时间可以在connectTimeout、和readTimeout中配置。
feign:
client:
config:
CLOUD-PAYMENT-SERVICE:
loggerLevel: FULL
connectTimeout: 5000
readTimeout: 5000
logging:
level:
com.xiaohui.springcloud.service.ProductFeignClient: debug
配置为FULL时的打印信息:
2020-11-27 20:48:38.893 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] ---> GET http://CLOUD-PAYMENT-SERVICE/payment/get/6203063 HTTP/1.1
2020-11-27 20:48:38.893 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] ---> END HTTP (0-byte body)
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] <--- HTTP/1.1 200 (20ms)
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] connection: keep-alive
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] content-type: application/json
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] date: Fri, 27 Nov 2020 12:48:38 GMT
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] keep-alive: timeout=60
2020-11-27 20:48:38.914 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] transfer-encoding: chunked
2020-11-27 20:48:38.915 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment]
2020-11-27 20:48:38.915 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] {"code":0,"message":"查询成功 server node:172.18.58.92:8002","data":{"id":6203063,"serial":"Hello SpringCloud"}}
2020-11-27 20:48:38.915 DEBUG 5832 --- [nio-9001-exec-8] c.x.s.service.ProductFeignClient : [ProductFeignClient#getPayment] <--- END HTTP (116-byte body)
五、项目完整文件及目录
父工程pom文件:
4.0.0
com.xiaohui.springCloud
SpringCloud
1.0-SNAPSHOT
pom
org.springframework.boot
spring-boot-starter-parent
2.2.2.RELEASE
product_service
cloud-api-common
eureka_server
openfeign_order_service
UTF-8
1.8
1.8
4.12
1.2.17
1.16.18
5.1.47
1.1.16
1.3.0
org.springframework.cloud
spring-cloud-dependencies
Hoxton.SR1
pom
import
com.alibaba.cloud
spring-cloud-alibaba-dependencies
2.1.0.RELEASE
pom
import
com.alibaba
druid
${druid.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.spring.boot.version}
mysql
mysql-connector-java
${mysql.version}
junit
junit
${junit.version}
org.projectlombok
lombok
${lombok.version}
true
org.springframework.boot
spring-boot-maven-plugin
true
true
1,openfeign_order_service 子模块 pom.xml
SpringCloud
com.xiaohui.springCloud
1.0-SNAPSHOT
4.0.0
openfeign_order_service
com.xiaohui.springCloud
cloud-api-common
${project.version}
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.retry
spring-retry
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-actuator
org.projectlombok
lombok
true
2,配置文件 application.yml:
server:
port: 9001
spring:
application:
name: openfeign-order-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://eureka1.com:9000/eureka/
instance:
prefer-ip-address: true #使用ip进行注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心注册服务ID
lease-renewal-interval-in-seconds: 5 #发送心跳间隔时间 秒
lease-expiration-duration-in-seconds: 10 # 服务续约时间 10秒内没有发送心跳(宕机)
CLOUD-PAYMENT-SERVICE:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
#Feign 日志输出配置
feign:
client:
config:
CLOUD-PAYMENT-SERVICE:
loggerLevel: FULL
connectTimeout: 5000
readTimeout: 5000
logging:
level:
com.xiaohui.springcloud.service.ProductFeignClient: debug
3,主启动类:
package com.xiaohui.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}
}
4,feign 接口类
package com.xiaohui.springcloud.service;
import com.xiaohui.springcloud.entities.CommonResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name="CLOUD-PAYMENT-SERVICE")
public interface ProductFeignClient {
@RequestMapping(value="/payment/get/{id}",method = RequestMethod.GET)
CommonResult getPayment(@PathVariable("id") Long id);
@GetMapping("/payment/get/timeout")
CommonResult getPaymentTimeout();
}
5,业务代码 controller
package com.xiaohui.springcloud.controller;
import com.xiaohui.springcloud.entities.CommonResult;
import com.xiaohui.springcloud.entities.Payment;
import com.xiaohui.springcloud.service.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private ProductFeignClient productFeignClient;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult getPayment(@PathVariable("id") Long id){
return productFeignClient.getPayment(id);
}
@GetMapping("/consumer/payment/get/timeout")
public CommonResult getPaymentTimeout(){
return productFeignClient.getPaymentTimeout();
}
}