背景
本意是想寫個feign中loadbalancer組件和nacos相遇後,一個兼容相關的問題,後面發現Feign這套東西很深,想一篇文章寫清楚很難,就先開一篇,講歷史。
Feign、OpenFeign、Spring Cloud OpenFeign
Feign
Feign是Java生態中的一個庫,這個庫的官方目標是:Feign makes writing Java http clients easier,大概就是讓http接口調用更加容易。
查了下歷史,最早是Netflix家的,座標如下,16年發佈了最後一個版本後停止維護:
<!-- https://mvnrepository.com/artifact/com.netflix.feign/feign-core -->
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
OpenFeign
2016年,Netflix將其捐贈給社區,改名OpenFeign,目前還一直在維護:
<dependency>
<groupId>io.github.openfeig</groupId>
<artifactId>feign-core</artifactId>
</dependency>
Spring Cloud OpenFeign
而Spring Cloud OpenFeign則是對Feign的集成,讓Feign能更方便地在spring項目中使用。
項目主頁:https://spring.io/projects/spring-cloud-openfeign#learn
Spring cloud這塊有兩個座標,一個是用於集成改名前的Feign,最早的版本是2015年,目前,這個座標早就標記爲過期了,提示使用另一個: Spring Cloud Starter Feign (deprecated, please use spring-cloud-starter-openfeign)
https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-feign
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
另一個則是集成改名後的OpenFeign,最早的版本是2017年11月20日,目前一直在維護,算是spring cloud中的核心組件:
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
值得一提的是,不管是哪一個座標,都是在第一個版本中,就已經依賴了ribbon這個組件,ribbon主要負責客戶端負載均衡,因爲根據服務名從服務註冊中心會拿到很多實例,具體調用哪一個,就得靠ribbon這個組件來選擇其中一個,比如隨機、輪詢等算法:
spring-cloud-starter-openfeign:
詳情可參考文章:https://juejin.cn/post/7097124836496900127
Feign使用示例
在feign中,比如要調用github的兩個接口,只需要向下面這樣定義好接口:
interface GitHub {
@RequestLine("GET /repos/{owner}/{repo}/contributors")
List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
@RequestLine("POST /repos/{owner}/{repo}/issues")
void createIssue(Issue issue, @Param("owner") String owner, @Param("repo") String repo);
}
調用就像下面這樣:
// 發起調用,調用第一個接口
GitHub github = Feign.builder().target(GitHub.class, "https://api.github.com");
List<Contributor> contributors = github.contributors("OpenFeign", "feign");
可以看出,它的思路就是簡潔,就像調用普通的方法一樣,不用考慮序列化、反序列化、流的打開和關閉、異常處理。
ribbon、spring cloud loadbalancer
我應該是18/19年開始在項目裏使用spring cloud,那時候的版本,還是spring cloud Netflix那一套,eureka + feign(ribbon) + hystrix斷路器 + zuul網關那一套,ribbon是由OpenFeign默認引入的。
後來,Netflix宣佈不再維護後,這一套中的組件,慢慢被替代。
前兩年在鵝廠沒搞spring cloud這一套,現在再搞這一套的時候,各個組件已經變天了。
在我們這,目前是,eureka變成了nacos,feign(ribbon)變成了feign(spring cloud loadbalancer),hystrix變成了sentinel,zuul網關變成了spring cloud gateway。
其中,feign是比較有意思的,之前的默認負載均衡組件是ribbon,但是ribbon因爲也是Netflix家的,不再維護後,spring官方自己搞了個spring cloud loadbalancer。
spring cloud openfeign是從什麼時候開始支持自家的loadbalancer呢?我翻了下歷史,在2.1.5.RELEASE版本,都還只有ribbon(https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign/2.1.5.RELEASE)
下一個版本是2.2.0.RELEASE,已經開始支持loadbalancer了(https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign/2.2.0.RELEASE)。
當然,ribbon也還是支持的,只是多了個選擇。
spring cloud loadbalancer的最早版本也就是2.2.0.RELEASE,想必就是爲了和openfeign的版本保持一致。
ribbon落幕
我發現,OpenFeign目前主要有幾個大版本。
2.2.x(從2.2.0.RELEASE到從2.2.10.RELEASE),這個版本都是有ribbon的,當然也有loadbalancer;
3.0.x,該版本是不帶ribbon的,只有loadbalancer;
3.1.x,4.0.x,4.1.x,都是不帶ribbon的,只有loadbalancer。
理清歷史有什麼用
理清歷史,可以讓你對項目中的依賴和配置項更有掌控。
比如,ribbon和loadbalancer只需要一個就夠了,沒必要共存,那你會說,我肯定不會兩個依賴同時引入。
沒錯,但是ribbon可能作爲如下依賴的間接依賴被引入:
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
也就是說,nacos服務發現的2.2.x系列,默認引入ribbon。
這樣的話,你就可以排除掉多餘的。
但你如果用的是nacos的2021.0.x系列,則它已經自己排除了ribbon系列,只支持loadbalancer了,就不需要手動排除了。
我就說我們有個項目很奇怪,爲啥要手動排除ribbon:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<groupId>org.springframework.cloud</groupId>
</exclusion>
</exclusions>
</dependency>
我才發現,是項目的nacos服務發現座標,從當時的2.2.x,升級到了:2021.0.5.0。我就說,排除個啥呀,本來都沒這個依賴。
另外,之前還需要手動禁用ribbon:
spring:
cloud:
loadbalancer:
ribbon:
enabled: false
沒理清楚這個歷史前,我還不敢去掉這段配置,現在呢,直接刪了就是。
這裏,總結一下,就是說,如果項目裏ribbon和loadbalancer共存,首先,這是沒啥必要的,其次,共存情況下要使用loadbalancer,則還是需要上面這段禁用ribbon的配置的。
參考文章
這篇是loadbalancer誕生的簡介。
https://spring.io/blog/2020/03/25/spring-tips-spring-cloud-loadbalancer