• 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年发布了最后一个版本后停止维护:

    Copy
    com.netflix.feign feign-core

    OpenFeign#

    2016年,Netflix将其捐赠给社区,改名OpenFeign,目前还一直在维护:

    Copy
    <dependency> <groupId>io.github.openfeiggroupId> <artifactId>feign-coreartifactId> 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)

    Copy
    https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-feign <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-feignartifactId> <version>1.0.0.RELEASEversion> dependency>

    另一个则是集成改名后的OpenFeign,最早的版本是2017年11月20日,目前一直在维护,算是spring cloud中的核心组件:

    Copy
    <dependency> <groupId>org.springframework.cloudgroupId> <artifactId>spring-cloud-starter-openfeignartifactId> <version>1.4.0.RELEASEversion> dependency>

    值得一提的是,不管是哪一个坐标,都是在第一个版本中,就已经依赖了ribbon这个组件,ribbon主要负责客户端负载均衡,因为根据服务名从服务注册中心会拿到很多实例,具体调用哪一个,就得靠ribbon这个组件来选择其中一个,比如随机、轮询等算法:

    image-20231214210600179

    spring-cloud-starter-openfeign:

    image-20231214210651652

    详情可参考文章:https://juejin.cn/post/7097124836496900127

    Feign使用示例#

    在feign中,比如要调用github的两个接口,只需要向下面这样定义好接口:

    Copy
    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); }

    调用就像下面这样:

    Copy
    // 发起调用,调用第一个接口 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可能作为如下依赖的间接依赖被引入:

    Copy
    <!-- 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:

    Copy
    <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:

    Copy
    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




  • 相关阅读:
    设计模式:享元模式 (我称之为网盘小视频模式/共享单车模式)
    docker搭建MySQL主从复制
    【牛客】SQL139 近三个月未完成试卷数为0的用户完成情况-窗口函数
    【Python】Matplotlib可视化50例
    【打卡】牛客网:BM45 滑动窗口的最大值
    详细教程:Postman 怎么调试 WebSocket
    SpringMVC原理学习(一)RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter
    python+cuda编程(一)
    【ACWing 算法基础】字符串哈希
    【力扣 - 多数元素】
  • 原文地址:https://www.cnblogs.com/grey-wolf/p/17902335.html