📚 目录
-
为什么要用OpenFeign?
-
在cart-service中整合OpenFeign
2.1 引入依赖
2.2 启用OpenFeign
2.3 编写Feign客户端
2.4 调用Feign接口
-
开启连接池,优化Feign性能
3.1 引入OkHttp
3.2 配置启用OkHttp连接池
3.3 验证连接池生效
-
Feign最佳实践 ------ 客户端抽取
4.1 避免重复编码问题
4.2 抽取公共Feign模块
4.3 配置扫描路径
-
配置OpenFeign日志输出
-
总结
1. 为什么要用OpenFeign?
在微服务中,服务与服务之间频繁调用。传统使用RestTemplate
需要自己管理服务发现、负载均衡、URL拼接,代码复杂且难以维护。
OpenFeign的优势:
-
声明式接口开发,像调用本地方法一样调用远程服务
-
内置负载均衡,支持 Ribbon、LoadBalancer
-
支持连接池,支持超时重试、熔断降级
-
支持详细日志输出,方便排查问题
✅ 一句话总结:OpenFeign让远程调用优雅又高效!
2. 在cart-service中整合OpenFeign
以 cart-service 查询我的购物车 为例,来演示整合OpenFeign。
2.1 引入依赖
在 cart-service
的 pom.xml
中添加:
<!-- 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>
2.2 启用OpenFeign
在 CartApplication
启动类上添加注解:
@EnableFeignClients
表示开启Feign客户端扫描。
2.3 编写Feign客户端
在 com.hmall.cart.client
包下,新建接口 ItemClient
:
@FeignClient("item-service")
public interface ItemClient {
@GetMapping("/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}
说明:
-
@FeignClient("item-service")
:指向要调用的微服务 -
@GetMapping("/items")
:对应远程接口路径 -
@RequestParam("ids")
:请求参数 -
返回值会自动封装成
List<ItemDTO>
2.4 调用Feign接口
在 CartServiceImpl
中直接注入 ItemClient
,然后调用即可:
@Autowired
private ItemClient itemClient;
// 调用
List<ItemDTO> items = itemClient.queryItemByIds(cartItemIds);
✅ 不需要再写 RestTemplate
、不需要自己负载均衡,调用清晰简单!
3. 开启连接池,优化Feign性能
默认Feign底层用的是HttpURLConnection
,不支持连接池,不适合高并发。
推荐使用 OkHttp 作为Feign底层,提高性能。
3.1 引入OkHttp依赖
在 cart-service
的 pom.xml
中添加:
<!-- OKHttp -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
3.2 配置启用OkHttp连接池
在 application.yml
中增加配置:
feign:
okhttp:
enabled: true
✅ 这样Feign就会自动使用OkHttp作为底层HTTP客户端,并且自动使用连接池。
3.3 验证连接池生效
在 FeignBlockingLoadBalancerClient
的 execute
方法打断点调试,可以看到底层已经是 OkHttpClient
了,说明连接池生效了!
4. Feign最佳实践 ------ 客户端抽取
未来 trade-service
也需要调用 item-service
的接口,重复定义 ItemClient
显然不合理,需要做客户端抽取!
4.1 避免重复编码问题
思路:把公共的Feign客户端抽取出来,供各个微服务引用。
4.2 抽取公共Feign模块
在项目下新建 hm-api
模块,pom.xml配置:
<artifactId>hm-api</artifactId>
<dependencies>
<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>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.6</version>
</dependency>
</dependencies>
然后将 ItemDTO
、ItemClient
移动到 hm-api
模块中。
4.3 配置扫描路径
在 cart-service
、trade-service
的启动类中添加:
-
方式一:声明扫描包
@EnableFeignClients(basePackages = "com.hmall.api.client")
-
方式二:指定特定FeignClient
@EnableFeignClients(clients = {ItemClient.class})
这样就可以正常引用公共模块中的Feign接口了!
5. 配置OpenFeign日志输出
默认OpenFeign日志级别是 NONE
,不会打印请求和响应信息。开发测试时开启详细日志很有必要。
5.1 定义日志配置类
在 hm-api
模块新增配置类:
@Configuration
public class DefaultFeignConfig {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.FULL;
}
}
设置日志级别为 FULL
,打印完整请求与响应数据。
5.2 配置日志生效方式
-
局部生效 :在单个
FeignClient
中指定@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
-
全局生效 :在
@EnableFeignClients
中指定@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)
5.3 日志示例
输出示例(查询商品接口):
[ItemClient#queryItemByIds] ---> GET http://item-service/items?ids=1001 HTTP/1.1
[ItemClient#queryItemByIds] ---> END HTTP (0-byte body)
[ItemClient#queryItemByIds] <--- HTTP/1.1 200 (127ms)
...
{"id":1001,"name":"巴布豆拉拉裤","price":67100,"stock":10000,...}
✅ 可以清晰看到请求方法、URL、参数、响应内容,排查问题非常方便!
6. 总结
本篇完整讲解了如何在微服务项目中:
-
引入OpenFeign
-
实现声明式远程调用
-
优化连接池性能(使用OkHttp)
-
进行Feign客户端抽取复用
-
配置请求日志,方便开发调试
✅ OpenFeign让我们的微服务调用变得更加优雅、简洁、性能更高。
✅ 配合OkHttp和合理日志配置,是生产级SpringCloud微服务系统必不可少的实践!