📚 目錄
-
為什么要用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 {@Beanpublic 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微服務系統必不可少的實踐!