spring cloud生態中Feign、Ribbon、loadbalancer的一些歷史

背景

本意是想寫個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這個組件來選擇其中一個,比如隨機、輪詢等算法:

image-20231214210600179

spring-cloud-starter-openfeign:

image-20231214210651652

詳情可參考文章: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也還是支持的,只是多了個選擇。

image-20231214214228342

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。

image-20231214220634503

這樣的話,你就可以排除掉多餘的。

但你如果用的是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

https://baijiahao.baidu.com/s?id=1662947934543573780

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章