什么是 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.RELEASE
、Spring 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
的文章。
🤗 您的點贊
和轉發
是對我最大的支持。
📢 掃碼關注 哈嘍沃德先生
「文檔 + 視頻」每篇文章都配有專門視頻講解,學習更輕松噢 ~