簡介:負載均衡(Load Balance)就是將用戶的請求平均的分配到多個服務上,從而達到系統的高可用,它是一種算法,可以通過該算法實現從地址列表中獲取一個地址進行服務調用,LB實現方式包含集中式(在消費者和服務提供方中間使用獨立的代理方式進行負載均衡)和進程內(根據自己的請求情況做負載均衡)兩種。
一、Ribbon
簡介:Ribbon用於實現軟負載均衡,核心三點:服務發現,發現依賴服務的列表、服務選擇規則,在多個服務中如何選擇一個有效服務、服務監聽,檢測失效的服務,高效剔除失效服務。
1. Ribbon與Nginx比較
A. Nginx:服務器負載均衡,客戶端所有請求都會交給Nginx,然后Nginx實現轉發請求,屬於集中式實現負載均衡;
B. Ribbon:本地負載均衡,在調用微服務接口的時候,會在注冊中心上獲取注冊信息服務列表后緩存到本地,從而在本地實現RPC遠程服務調用,屬於進程內實現負載均衡。
2. pom.xml Maven依賴
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency>
3. application.yml 文件配置
ribbon: # 全局連接超時時間(使用url路由方式配置不生效) ConnectTimeout: 5000 # 全局請求超時時間(使用url路由方式配置不生效) ReadTimeout: 15000 # 同一台實例最大重試次數,不含首次調用 MaxAutoRetries: 0 # 重試負載均衡其他實例的最大重試次數,不含首次調用 MaxAutoRetriesNextServer: 0
Ribbon總時間ribbonTimeout = (ribbon.ConnectTimeout + ribbon.ReadTimeout) * (ribbon.MaxAutoRetries + 1) * (ribbon.MaxAutoRetriesNextServer + 1);其中histry的timeoutInMilliseconds值應大於或等於ibbonTimeout,否則出現下面錯誤。
o.s.c.n.z.f.r.s.AbstractRibbonCommand : The Hystrix timeout of 15000ms for the command *** is set lower than the combination of the Ribbon read and connect timeout, 20000ms
4. Ribbon注解
A. @LoadBalanced:啟動Ribbon的負載均衡策略;
B. @RibbonClient(name = "service-name", configuration = RuleConfig.class):自定義負載均衡策略;
name —— 服務名稱
configuration —— 負載均衡配置類
C. @RibbonClients(defaultConfiguration = RuleConfig.class):全局配置自定義負載均衡策略
defaultConfiguration —— 負載均衡配置類
5. Ribbon核心類組成
接口 | 作用 | 默認值 |
IClientConfig | 讀取配置 | DefaultClientConfigImpl |
IRule | 負載均衡規則,選擇實例 | ZoneAvoidanceRule |
IPing | 篩選ping不通的實例 | DummyPing |
ServerList <Sever> | 交給Ribbon的實例列表 | ConfigurationBaseServerList |
ServerListFilter <Sever> | 過濾掉不符合條件的實例 | ZonePreferenceServerListFilter |
ILoadBalancer | Ribbon的入口 | ZoneAwareLoadBalancer |
ServerListUpdater | 更新交給Ribbon的List的策略 | PollingServerListUpdater |
6. Ribbon負載均衡策略
默認是ZoneAvoidanceRule,它是一個按照地域方式來進行負載均衡,但是在沒有zone的情況下就是輪詢(RoundRobinRule)。
負載均衡規則類 | 作用 |
RoundRobinRule | 輪詢選擇, 輪詢index,選擇index對應位置的Server |
AvailabilityFilteringRule | 過濾掉那些一直連接失敗的被標記為circuit tripped的后端Server,並過濾掉那些高並發的的后端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就就是檢查status里記錄的各個Server的運行狀態 |
WeightedResponseTimeRule | 根據響應時間分配一個weight(權重),響應時間越長,weight越小,被選中的可能性越低 |
ZoneAvoidanceRule | 復合判斷Server所在區域的性能和Server的可用性選擇Server |
BestAvailableRule | 選擇一個最小的並發請求的Server,逐個考察Server,如果Server被tripped了,則跳過 |
RandomRule | 隨機選擇一個Server |
RetryRule | 對選定的負載均衡策略上重試機制,在一個配置時間段內當選擇Server不成功,則一直嘗試使用subRule的方式選擇一個可用的server |
7. 實現負載均衡的方式
Eureka中已經集成了Ribbon,所以無需引入新的依賴;如果兩種方式都配置,則以java代碼配置為准。
A. 基於application.yml配置文件
# service-name代表服務名稱 service-name: ribbon: NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
B. 基於java代碼
會引起父子上下文掃描重疊問題,這個會導致事務失效,解決方案是規則的定義(放在啟動類之外的包目錄下)和引入分開寫隔離。可參考:Spring父子上下文重疊
package com.ruhaunxingyun.ribbon; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.RandomRule; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @description: 自定義負載均衡策略 * @author: ruphie * @date: Create in 2020/8/16 13:56 * @company: ruhuanxingyun */ @Configuration public class RuleConfig { @Bean public IRule myRule() { return new RandomRule(); } }
C. 兩種方式的對比:代碼配置優點是靈活,但存在上下文重疊的問題,修改以后需要重新打包;配置文件配置容易上手,配置更加直觀,線上修改無需重新打包,發布優先級更高,缺點是若自定義規則需要代碼配置。