Spring Cloud 系列之 Netflix Ribbon 負載均衡


什么是 Ribbon

  

  Ribbon 是一個基於 HTTP 和 TCP 的 客服端負載均衡工具,它是基於 Netflix Ribbon 實現的。

  它不像 Spring Cloud 服務注冊中心、配置中心、API 網關那樣獨立部署,但是它幾乎存在於每個 Spring Cloud 微服務中。包括 Feign 提供的聲明式服務調用也是基於該 Ribbon 實現的。

  Ribbon 默認提供很多種負載均衡算法,例如輪詢、隨機等等。甚至包含自定義的負載均衡算法。

  

Ribbon 解決了什么問題

  

  Ribbon 提供了一套微服務的負載均衡解決方案。

  

負載均衡不同方案的區別

  

  目前業界主流的負載均衡方案可分成兩類:

  • 集中式負載均衡(服務器負載均衡),即在 consumer 和 provider 之間使用獨立的負載均衡設施(可以是硬件,如 F5,也可以是軟件,如 nginx),由該設施負責把訪問請求通過某種策略轉發至 provider;
  • 進程內負載均衡(客戶端負載均衡),將負載均衡邏輯集成到 consumer,consumer 從服務注冊中心獲知有哪些地址可用,然后自己再從這些地址中選擇出一個合適的 provider。Ribbon 屬於后者,它只是一個類庫,集成於 consumer 進程,consumer 通過它來獲取 provider 的地址。

  

集中式負載均衡

  

  

進程內負載均衡

  

  

Ribbon 負載均衡策略

  

輪詢策略(默認)

  

  策略對應類名:RoundRobinRule

  實現原理:輪詢策略表示每次都順序取下一個 provider,比如一共有 5 個 provider,第 1 次取第 1 個,第 2 次取第 2 個,第 3 次取第 3 個,以此類推。

  

權重輪詢策略

  

  策略對應類名:WeightedResponseTimeRule

  實現原理:

  • 根據每個 provider 的響應時間分配一個權重,響應時間越長,權重越小,被選中的可能性越低。
  • 原理:一開始為輪詢策略,並開啟一個計時器,每 30 秒收集一次每個 provider 的平均響應時間,當信息足夠時,給每個 provider 附上一個權重,並按權重隨機選擇 provider,高權越重的 provider 會被高概率選中。

  

隨機策略

  

  策略對應類名:RandomRule

  實現原理:從 provider 列表中隨機選擇一個。

  

最少並發數策略

  

  策略對應類名:BestAvailableRule

  實現原理:選擇正在請求中的並發數最小的 provider,除非這個 provider 在熔斷中。

  

重試策略

  

  策略對應類名:RetryRule

  實現原理:其實就是輪詢策略的增強版,輪詢策略服務不可用時不做處理,重試策略服務不可用時會重新嘗試集群中的其他節點。

  

可用性敏感策略

  

  策略對應類名:AvailabilityFilteringRule

  實現原理:過濾性能差的 provider

  • 第一種:過濾掉在 Eureka 中處於一直連接失敗的 provider。
  • 第二種:過濾掉高並發(繁忙)的 provider。

  

區域敏感性策略

  

  策略對應類名:ZoneAvoidanceRule

  實現原理:

  • 以一個區域為單位考察可用性,對於不可用的區域整個丟棄,從剩下區域中選可用的 provider。
  • 如果這個 ip 區域內有一個或多個實例不可達或響應變慢,都會降低該 ip 區域內其他 ip 被選中的權
    重。

  

Ribbon 入門案例

  

  點擊鏈接觀看:Ribbon 入門案例視頻(獲取更多請關注公眾號「哈嘍沃德先生」)

  eureka-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  Ribbon 中對於集群的服務采用的負載均衡策略默認是輪詢。

  

創建項目

  

  使用學習 Eureka 時的 eureka-demo 項目,在該項目中創建子項目 service-provider02

  

添加依賴

  

  pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>service-provider02</artifactId>
    <version>1.0-SNAPSHOT</version>

    <!-- 繼承父依賴 -->
    <parent>
        <groupId>com.example</groupId>
        <artifactId>eureka-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <!-- 項目依賴 -->
    <dependencies>
        <!-- netflix eureka client 依賴 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- spring boot web 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- lombok 依賴 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <!-- spring boot actuator 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!-- spring boot test 依賴 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
  
</project>

  

配置文件

  

  application.yml

server:
  port: 7071 # 端口

spring:
  application:
    name: service-provider # 應用名稱(集群下相同)

# 配置 Eureka Server 注冊中心
eureka:
  instance:
    prefer-ip-address: true       # 是否使用 ip 地址注冊
    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port
  client:
    service-url:                  # 設置服務注冊中心地址
      defaultZone: http://root:123456@localhost:8761/eureka/,http://root:123456@localhost:8762/eureka/

# 度量指標監控與健康檢查
management:
  endpoints:
    web:
      exposure:
        include: shutdown         # 開啟 shutdown 端點訪問
  endpoint:
    shutdown:
      enabled: true               # 開啟 shutdown 實現優雅停服

  

服務及啟動類

  

  將所有代碼復制粘貼一份至 server-provider02,修改啟動類名稱即可。

  ServiceProvider02Application.java

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ServiceProvider02Application {

    public static void main(String[] args) {
        SpringApplication.run(ServiceProvider02Application.class, args);
    }

}

為了更直觀的看到負載均衡的效果,我們在 service-consumer 項目中將服務地址打印至控制台。

  

注冊中心

  

  運行完整的 Eureka 環境,訪問:http://localhost:8761/ 可以看到現在已經有兩個服務提供者。

  

消費服務

  

  多次訪問:http://localhost:9090/order/1 可以看到默認使用的是輪詢策略。

  

Ribbon 負載均衡策略設置

  

全局

  

  在啟動類或配置類中注入負載均衡策略對象。所有服務請求均使用該策略。

@Bean
public RandomRule randomRule() {
    return new RandomRule();
}

  多次訪問:http://localhost:9090/order/1 結果如下:

  

局部

  

  修改配置文件指定服務的負載均衡策略。格式:服務應用名.ribbon.NFLoadBalancerRuleClassName

# 負載均衡策略
# service-provider 為調用的服務的名稱
service-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

  多次訪問:http://localhost:9090/order/1 結果如下:

  

Ribbon 點對點直連

  

  點擊鏈接觀看:Ribbon 點對點直連視頻(獲取更多請關注公眾號「哈嘍沃德先生」)

  點對點直連是指繞過注冊中心,直接連接服務提供者獲取服務,一般在測試階段使用比較多。

  

添加依賴

  

  在調用方 pom 文件中引入 ribbon 依賴,需要注意的是如果 pom 中有 Eureka 的依賴,則需要去除 Eureka 的依賴。

<!-- netflix ribbon 依賴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

  

配置文件

  

  配置文件中關閉 Eureka,添加直連的服務地址。如果不設置負載均衡策略默認使用輪詢策略。

# 負載均衡策略
# service-provider 為調用的服務的名稱
service-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    # 指定具體的 Provider 服務列表,多個用逗號隔開
    listOfServers: http://localhost:7070,http://localhost:7071

# 關閉 Eureka 實現 Ribbon 點對點直連
ribbon:
  eureka:
    enabled: false # false:關閉,true:開啟

  

訪問

  

  關閉 Eureka 注冊中心,服務提供者由於無法連接至注冊中心所以會報連接異常。但是服務是可以正常可消費的,所以目前使用的是點對點的方式來進行調用的。

  多次訪問:http://localhost:9090/order/1 結果如下:

  至此 Ribbon 負載均衡所有的知識點就講解結束了。

  本文采用 知識共享「署名-非商業性使用-禁止演繹 4.0 國際」許可協議

  大家可以通過 分類 查看更多關於 Spring Cloud 的文章。

  

  🤗 您的點贊轉發是對我最大的支持。

  📢 掃碼關注 哈嘍沃德先生「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕松噢 ~


免責聲明!

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



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