背景
本意是想寫個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