Spring Cloud之Ribbon負載均衡(Spring Cloud 2020.0.3版)


Spring Cloud Ribbon

 

demo代碼放在github上 ,需要的請點這里--> demo

1. Ribbon簡介

一般來說,在生產環境中,各個微服務都會部署多個實例。那么消費者要如何將請求分攤到多個服務提供者實例上呢?負載均衡在系統架構中一個非常重要,不得不去實施的內容,負載均衡是對系統的高可用、網絡壓力的緩解和處理能力擴容的重要手段之一。通常所說的負載均衡都是指服務端負載均衡,其中分為硬件負載均衡(如F5)和軟件負載均衡(如Nginx)。Ribbon是NetFlix發布的客戶端負載均衡器,它有助於控制Http和Tcp客戶端的行為。通過SpringCloud的封裝,可以讓我們輕松的將面向服務的REST模板請求自動轉換成客戶端負載均衡的服務調用。Spring Cloud Ribbon雖然只是一個工具類框架,它不像服務注冊中心、配置中心、API網關那樣需要獨立部署,但是它幾乎存在於每一個SpringCloud構建的微服務和基礎設施中。

客戶端負載均衡和服務端負載均衡的區別?

TODO: 最大的區別就是服務清單存儲的位置,

  • 服務端負載均衡

image-20210517151757123

2. Ribbon的使用

  1. 通過Spring Cloud Ribbon的封裝,在微服務架構中使用客戶端負載均衡調用非常簡單,只需要如下兩步:

    • 服務提供者只需要啟動多個服務實例並注冊到服務注冊中心

    • 服務消費者直接通過調用被@LoadBalanced注解修飾過的RestTemplate來實現面向服務的接口調用

  2. 具體布步驟如下:

    1. 在服務消費者微服務的POM文件中添加ribbon的依賴

      <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.8.RELEASE</version>
      </dependency>

      在spring cloud Eureka依賴中已經包含了spring cloud ribbon,因此無需再次引入。如過已經添加了的spring cloud Eureka依賴,不要添加該依賴,否則會遇到空指針錯誤。

    2. 服務提供者微服務中給RestTemplate添加@LoadBalanced注解

      @Bean
          @LoadBalanced
          public RestTemplate restTemplate()
          {
              return new RestTemplate();
          }

      image-20210517160434607

    3. 對服務消費者的controller代碼進行修改

       @Autowired
          private RestTemplate restTemplate;
      ​
          @Autowired
          private LoadBalancerClient loadBalancerClient;
      ​
          @GetMapping("/user/{id}")
          public User findById(@PathVariable long id)
          {
              //hardCode硬編碼方式不可取
             //return restTemplate.getForObject("http://localhost:8000/" + id,User.class);
      //修改成通過微服務的虛擬主機名來訪問
              return restTemplate.getForObject("http://userservice/"+id,User.class);
          }
      ​
          @GetMapping("/log-user-instance")
          public void logUserInstances()
          {
              ServiceInstance serviceInstance = loadBalancerClient.choose("userservice");
              log.info("serviceId-->{},Host-->{},port-->{}",serviceInstance.getServiceId(),serviceInstance.getHost(),serviceInstance.getPort());
          }

       

      新增加了一個API接口,服務消費者訪問該接口時打印出IP地址和端口號

      image-20210517160749653

    4. 現在分別啟動1個服務注冊中和2個服務提供者、1個服務消費者

      • 服務注冊中心

        image-20210517161222111

         

      • 服務提供者

        image-20210517161324308

        這里提供一下如何在idea中如何啟動兩個不同端口號的服務提供者的實例

        • 在服務提供者的配置文件中已經配置了server.port=8000,因此第一個實例直接點擊運行就可以咯

          image-20210517162309499

        • 選擇Idea右上角啟動按鈕邊上的Edit Configurations,在打開的對話框中,選擇UserServiceApplication-->點擊復制按鈕->VM Options中增加-Dserver.port=8001,Apply應用,如圖:

          image-20210517162438058

          最后點擊運行就可以運行port=8001的實例咯

      • 服務消費者

        啟動服務消費者,然后不斷的訪問API接口地址http://localhost:8081/log-user-instance,發現交替打印服務消費者的ip地址。

        image-20210517163043521

搭建過程中遇到的問題:

添加該依賴后,運行時報空指針錯誤,去掉該依賴后能正常訪問。image-20210517175714002

報錯信息如下:

image-20210517175601096

出現該問題的根本原因是Spring Cloud 2020.0.0版本以后對Spring Cloud NetFlix 組件進行剔除,僅保留了Eureka組件,其核心組件 Hystrix、Ribbon、Zuul、Archaius 等均進入維護狀態


舊版本的spring-cloud-netflix-dependencies管理着Netflix所有組件,包括Hystrix、Ribbon、Zuul、Eureka等。而自2020.0版本起,它有且只管理Eureka(包括Server和Client)
其中Feign雖然最初屬Netflix公司,但從9.x版本開始就移交給OpenFeign組織管理了,因此不再划入Netflix管轄范疇。

簡單一句話概括:Spring Cloud 2020.0.0版本徹底刪除掉了Netflix除Eureka外的所有組件

image-20210518111000347

Spring Cloud 既然把 Netflix 套件大刀闊斧的砍掉了,那總歸得有替代方案吧。那是必然的,Spring Cloud 團隊給我們推薦了用於替代的組件:

image-20210518110911185

image-20210518112004676

Spring Cloud LoadBalancer 目前僅支持輪詢負載均衡策略,相對於 Ribbon 多種高可用策略還是過於簡單。

3. Ribbon負載均衡策略

很多場景下,可能根據需要自定義Ribbon的配置,例如修改Ribbon的負載均衡規則等。

方法一和二適合於Spring Cloud 2020.0.0版本之前的版本,方法三適合Spring Cloud 2020.0.0版之后的Spring Cloud版本

方法一:配置文件的方式

在application.propertites文件中添加如下代碼:

#更改負載均衡的負載策略
userservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

image-20210517223443589

方法二:使用Java代碼自定義Ribbon配置

使用Ribbon提供的負載均衡策略很簡單

  • 創建具有負載均衡功能的RestTemplate實例

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

    使用RestTemplate進行rest操作的時候,會自動使用負載均衡策略,它內部會在RestTemplate中加入LoadBalancerInterceptor這個攔截器,這個攔截器的作用就是使用負載均衡。

  • 默認情況下會采用輪詢策略,如果希望采用其它策略,則指定IRule實現,如:

    @Bean
    public IRule ribbonRule() {
        return new BestAvailableRule();
    }

方法三:負載均衡策略配置(適用於Spring Cloud 2020.0.0版之后的版本

spring cloud加入了一個新模塊Spring-Loadbalancer來替代ribbon,有兩種負載均衡模式(輪詢和隨機),默認是用輪詢,假如想使用隨機或者自定義負載均衡策略,就不能按照以前使用ribbon的模式(注入IRule類,必須引入ribbon依賴),那么如果我使用Loadbalancer的隨機負載均衡,要怎么設置呢?官網給出比較詳細的方法

顯然官方寫了一個切換成隨機負載均衡的例子,我們拷貝過來即可。

image-20210518112950963

@Bean
        ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                                LoadBalancerClientFactory loadBalancerClientFactory) {
            String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
            return new RandomLoadBalancer(loadBalancerClientFactory
                    .getLazyProvider(name, ServiceInstanceListSupplier.class),
                    name);
​
  • 搭建步驟

    1. 把官方的@Bean方法拷貝到自己的配置類(這個類可以放到主啟動類所在包及子包下,這一點和Ribbon不同

      image-20210518114000731

    2. 在啟動類,使用@LoadBalancerClient或者@LoadBalancerClients注解,加載自己的配置類,由此切換loadBalancer默認的負載均衡策略

      image-20210518114034152

    3. 然后運行代碼發現就切換成隨機負載均衡策略咯

image-20210518113209128

4. Ribbon自定義負載均衡策略

可以參考這篇博客: https://blog.csdn.net/qq_35799668/article/details/114534023

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM