SpringCloud Feign 声明式服务调用

2022-07-20 13:36:30

服务调用有2种方式:rest、rpc,springcloud使用RestTemplate实现rest调用,还可以使用feign进行声明式的远程http服务调用,所谓声明式就是通过服务接口来调用,和rpc相似。

使用feign进行服务调用

feign是一种服务调用方式,自然是在消费者中使用的

1、创建时勾选Spring Cloud Routing -> OpenFeign,或者手动添加依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>

2、引导类上加 @EnableFeignClients

//如果不指定basePackages,默认会扫描所有的包@EnableFeignClients(basePackages="com.chy.mall.feignclient")

在引导类上加@EnableXxx的,在启动时会扫描相关注解。

3、新建包feignclient用来存放feign服务调用的接口

@FeignClient("order-service")//指定要调用的服务名称。feign也内置了ribbon,会自动实现负载均衡@RequestMapping("/order")publicinterfaceOrderServiceFeignClient{@GetMapping("/list/{user_id}")//指定地址
    List<Order>findOrdersByUserId(@PathVariable("user_id") Integer userId);}

可以使用springmvc的注解绑定参数。

@FeignClient(name=“order-service”),name的别名是value,也可以写成@FeignClient(value=“order-service”),注解特性可以缺省value。

4、service

@ServicepublicclassUserService{@Autowiredprivate OrderServiceFeignClient orderServiceFeignClient;//注入要使用的Feign接口public List<Order>findOrdersById(Integer userId){//通过Feign接口进行服务调用return orderServiceFeignClient.findOrdersByUserId(userId);}}

feign的常用配置项

以feign的日志配置为例,一般的日志直接在logging.level中配置即可,feign的日志配置方式有些不同,就算把日志级别设置为debug,feign默认也不会输出任何日志。

feign有自己的日志级别

  • NONE:默认值,不打印任何日志
  • BASIC: 只打印请求方法、url、响应状态码、执行时间
  • HEADERS:在BASIC的基础上,会打印请求、响应的header
  • FULL:打印请求、响应的header、body、元数据,可以看到提供者返回的数据。

生产环境一般用BASIC,输出日志少,性能好;开发环境一般用FULL,方便调试。

代码配置方式

yml

logging:level:root: info#feign打印日志的前提是feign接口的日志级别是debug,因为feign输出的日志是debug级别com.chy.mall.feignclient: debug


配置类 config.FeignClientConfig

import feign.Logger;import org.springframework.context.annotation.Bean;/**
 * 定义feign接口的日志级别
 * 不要加@Configuration
 */publicclassFeignClientConfig{@Beanpublic Logger.Levellevel(){return Logger.Level.FULL;}}


引导类

//指定feign的配置类@EnableFeignClients(basePackages="com.chy.mall.feignclient", defaultConfiguration= FeignClientConfig.class)//上面是全局配置,给所有的feign接口指定,也可以分别给feign接口指定//@FeignClient("order-service", configuration = FeignClientConfig.class)

步骤也繁琐,不推荐。

属性配置方式(推荐)

logging:level:root: info#将feign接口的日志级别设置为debug,因为feign输出的日志是debug级别com.chy.mall.feignclient: debugfeign:client:config:#全局配置,指定所有feign服务调用的日志级别default:loggerLevel: full#也可以分别配置各个服务调用的#      order-server:#        loggerLevel: full#      msg-server:#        loggerLevel: full

无需其它配置。

除了loggerLevel,feign的其它常用配置项如下

  • connectTimeout: 10000  连接超时时间
  • readTimeout: 10000  读取超时时间

feign的继承特性

提供者提供接口,消费者中有要调用的接口声明,提供者修改了接口的映射地址、形参表、返回值类型,比如返回类型是实体类,现在需求变了,这个实体类要增删一些成员变量,提供者修改接口后,消费者也要同步修改,接口维护起来很麻烦。

feign的继承特性:将要服务之间要调用的接口、涉及的实体类提出来,单独写成一个模块,打成jar包在提供者、消费者中引入,然后提供者的controller实现接口,消费者的feign接口继承接口(无需再进行声明)。更改接口时,要稍微好维护一些。

官方不推荐使用feign的继承特性,因为会使服务耦合在一起,但实际使用的公司也不少。

传递多个参数

restful适合参数少的情况,如果参数较多,可以使用以下几种方式

  • feign接口、提供者的接口都使用 @RequestParam + 多个参数
  • feign接口、提供者的接口都使用 @RequestParam + Map<String,Object>
  • 提供者的接口用实体类声明参数,feign接口用 @SpringQueryMap + 实体类

第一二种都支持feign的继承特性,第三种不支持。

不建议使用Map接收参数,需要自己转换参数的数据类型,麻烦、易出错。

如果把@SpringQueryMap换成@RequestParam,可以调用服务,但传过去的实体的成员变量都是null。

脱离ribbon使用feign

ribbon是从自己的注册中心获取节点列表,如果是通过第三方的网关调用他们的服务,可以用HttpClient发起请求,也可以用feign发起请求,此时feign是脱离ribbon使用的。

//url指定请求地址,value指定服务名@FeignClient(value="xxx-server",url="http://www.xxx.com/xxx")

服务名是必需的,如果不指定服务名,启动不了应用。在指定了url的情况下,服务名可以随便写一个。

feign与RestTemplate的对比

feign 伪装、假装,feign只是伪rpc调用,实际使用的还是RestTemplate,使用的协议还是http。

  • feign性能要低于直接使用RestTemplate。feign是将RestTemplate包装为feign接口,生成动态代理,通过代理进行操作,有额外的开销,拉低了性能。
  • feign让代码可读性更好、易于维护。服务调用接口声明都聚集在一起,方便查看、修改;接口改动时只需修改feignclient包下的feign接口,无需找到所有的服务调用处,维护方便。

一般都是使用feign。

feign性能优化之配置连接池

feign默认使用urlconnection发起请求,不使用连接池;feign也支持用httpclient发起请求,可以使用feign-httpclient、okhttp等jar包提供的httpclient连接池。

httpclient

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId></dependency>
feign:#配置httpclient连接池httpclient:#默认trueenabled:true#feign连接池的最大连接数max-connections:200#feign连接池单个url的最大连接数max-connections-per-route:50

这些数值都是默认值,根据压测结果进行修改

okhttp

feign:okhttp:#默认falseenabled:true#配置httpclient连接池httpclient:#feign连接池的最大连接数max-connections:200#feign连接池单个url的最大连接数max-connections-per-route:50

当然,也可以使用其它提供了httpclient连接池的jar包,但需要指定jar包的<version>。

  • 作者:chy1984
  • 原文链接:https://blog.csdn.net/chy_18883701161/article/details/106459800
    更新时间:2022-07-20 13:36:30