一,OpenFeign
1.1 介绍
我们利用 Nacos 实现了服务的治理,利用 RestTemplate 实现了服务的远程调用。但是远程调用的代码太复杂了:

而且这种调用方式,与原本的本地方法调用差异太大,编程时的体验也不统一,一会儿远程调用,一会儿本地调用。
因此,我们必须想办法改变远程调用的开发模式,让远程调用像本地方法调用一样简单。而这就要用到 OpenFeign 组件了。
其实远程调用的关键点就在于四个:
- 请求方式
- 请求路径
- 请求参数
- 返回值类型
所以,OpenFeign 就利用 SpringMVC 的相关注解来声明上述 4 个参数,然后基于动态代理帮我们生成远程调用的代码,而无需我们手动再编写,非常方便。
1.2 快速入门
-
引入依赖
<!--openFeign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--负载均衡器--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> -
启用 OpenFeign
在启动类上添加注解,启动 OpenFeign 功能

-
编写 OpenFeign 客户端
package com.hmall.cart.client; import com.hmall.cart.domain.dto.ItemDTO; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; @FeignClient("item-service") public interface ItemClient { @GetMapping("/items") List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids); }这里只需要声明接口,无需实现方法。接口中的几个关键信息:
@FeignClient("item-service"):声明服务名称@GetMapping:声明请求方式@GetMapping("/items"):声明请求路径@RequestParam("ids") Collection<Long> ids:声明请求参数List<ItemDTO>:返回值类型
有了上述信息,OpenFeign 就可以利用动态代理帮我们实现这个方法,并且向
http://item-service/items发送一个GET请求,携带 ids 为请求参数,并自动将返回值处理为List<ItemDTO>。我们只需要直接调用这个方法,即可实现远程调用了。
-
使用 FeignClient

feign 替我们完成了服务拉取、负载均衡、发送 http 请求的所有工作,而且,这里我们不再需要 RestTemplate 了,还省去了 RestTemplate 的注册。
1.3 连接池
Feign 底层发起 http 请求,依赖于其它的框架。其底层支持的 http 客户端实现包括:
HttpURLConnection:默认实现,不支持连接池Apache HttpClient:支持连接池OKHttp:支持连接池
因此我们通常会使用带有连接池的客户端来代替默认的HttpURLConnection。比如,我们使用 OK Http.
-
引入依赖
<!--OK http 的依赖 --> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-okhttp</artifactId> </dependency> -
开启连接池
feign: okhttp: enabled: true # 开启OKHttp功能 -
验证
我们可以打断点验证连接池是否生效,在
org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient中的execute方法中打断点:

Debug方式启动cart-service,请求一次查询我的购物车方法,进入断点:

可以发现这里底层的实现已经改为`OkHttpClient`
注意:对于 Feign 客户端,业务上不会在单独一个服务里面创建,而是抽取成一个api-service模块,然后其他服务需要调用直接引入这个模块,从而降低重复的创建 Feign 客户端。
1.4 日志输出
OpenFeign 只会在 FeignClient 所在包的日志级别为DEBUG时,才会输出日志。而且其日志级别有 4 级:
- NONE:不记录任何日志信息,这是默认值。
- BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
- HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
- FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。
Feign 默认的日志级别就是 NONE,所以默认我们看不到请求日志。
-
定义日志级别
在
api-service模块下新建一个配置类,定义 Feign 的日志级别:package com.hmall.api.config; import feign.Logger; import org.springframework.context.annotation.Bean; public class DefaultFeignConfig { @Bean public Logger.Level feignLogLevel(){ return Logger.Level.FULL; } } -
配置
接下来,要让日志级别生效,还需要配置这个类。有两种方式:
-
局部生效:在某个
FeignClient中配置,只对当前FeignClient生效@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class) -
全局生效:在
@EnableFeignClients中配置,针对所有FeignClient生效。@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)
-
OpenFeign
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。