網站首頁 編程語言 正文
Spring Cloud Ribbon
簡介
Ribbon 是Netflix公司的一個開源的負載均衡項目,是一個客戶端/進程內負載均衡器,運行在消費者端。
這里引出一個問題客戶端負載均衡和服務端負載均衡的區別是什么呢?
客戶端負載均衡和服務端負載均衡最大的不同在于服務清單所在的位置。
客戶端負載均衡中,客戶端中都維護著自己要訪問的服務段清單,
而這些清單都來源于服務注冊中心(動態地址,例如配置中心Eureka,Consul,Etcd等)
或者本地(靜態地址,可以配置在配置文件中進行維護,不方便)。
但是服務端負載均衡的服務清單是無法自己來維護的,例如Nignx是接收到請求后
把請求轉發到系統應用中。
簡單使用
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.9.RELEASE</version>
</dependency>
@Configuration
public class RestTemplateConfiguration {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping
public String order(){
log.info("begin do order");
String url="http://goods-service/goods";
return goodsInfo=restTemplate.getForObject(url,String.class);
}
}
goods-service.ribbon.listOfServers=\
http://localhost:9090,http://localhost:9093
Ribbon連接數配置
Ribbon可以通過下面的配置項,來限制httpclient連接池的最大連接數量、以及針對不同host的最大連接數量。
Ribbon底層的網絡通信,采用的是HttpClient中的PoolingHttpClientConnectionManager連接池,連接池的好處是避免頻繁建立連接(針對單個目標地址)帶來的性能開銷,但是維護過多的鏈接會對客戶端造成內存以及維護上的成本。所以,可以通過MaxTotalConnections 限制總的連接數量,或者通過MaxConnectionsPerHost 限制針對每個host的最大連接數。
# 最大連接數
ribbon.MaxTotalConnections=200 (默認值:200)
# 每個host最大連接數
ribbon.MaxConnectionsPerHost=50 (默認值:50)
Ribbon核心之Ping機制
在ribbon負載均衡器中,提供了ping機制,每隔一段時間,就會去ping服務器,由com.netflix.loadbalancer.IPing 接口去實現。
單獨使用ribbon,不會激活ping機制,默認采用DummyPing(在RibbonClientConfiguration中實例化),isAlive()方法直接返回true。
ribbon和eureka集成,默認采用NIWSDiscoveryPing (在
EurekaRibbonClientConfiguration中實例化的),只有服務器列表的實例狀態為up的時候
才會為Alive。
IPing中默認內置了一些實現方法如下。
- PingUrl: 使用httpClient對目標服務逐個實現Ping操作
- DummyPing: 默認認為對方服務是正常的,直接返回true
- NoOpPing:永遠返回true
Ribbon中的負載均衡策略
負載均衡,不管Nginx還是Ribbon都需要其算法的支持,Nginx使用的是輪詢和加權輪詢算法。而在Ribbon中有更多的負載均衡調度算法,其默認是使用的RoundRobinRule輪詢策略。
-
RoundRobinRule:輪詢策略。Ribbon默認采用的策略。若經過一輪輪詢沒有找到可用的provider,其最多輪詢 10 輪。若最終還沒有找到,則返回 null。
-
RandomRule: 隨機策略,從所有可用的 provider 中隨機選擇一個。
-
RetryRule: 重試策略。先按照 RoundRobinRule 策略獲取 provider,若獲取失敗,則在指定的時限內重試。默認的時限為 500 毫秒。
-
WeightedRespinseTimeRule:權重輪詢。該策略是對RoundRobinRule的擴展,增加了根據實例的運行情況來計算權重,并根據權重來挑選實例,已達到更優的分配效果。
-
ClientConfigEnabledRoundRobinRule:該策略較為特殊,我們一般不直接使用它。因為它本身并沒有實現什么特殊的處理邏輯,真如代碼中所示,在他的內部定義了一個RoundRobinRule策略,而choose函數的實現也正是使用了RoundRobinRule的線性輪詢機制,所以它實現的功能實際上RoundeRobinRule相同。
雖然不能直接使用該策略,但是可以通過繼承該策略,默認的choose就實現了線性輪詢機制,但是可以在子類中實現更高級的策略 -
BestAvailableRule:最低并發策略。該策略通過遍歷負載均衡器中維護的所有實例,會過濾調故障的實例,并找出并發請求數最小的一個,所以該策略的特征是選擇出最空閑的實例
-
PredicateBaseRule:先通過子類中實現的Predicate邏輯來過濾一部分服務實例,然后再以線性輪詢的方式從過濾后的實例清單中選出一個。至于如何過濾,需要我們在AbstractServerPredicate的子類中實現apply方法來確定具體的實現策略。
-
ZoneAvoidanceRule:區域權衡策略。它是PredicateBaseRule的具體實現類,從它的源碼中可以看到它是通過CompositePredicate來進行服務實例清單額過濾的。這是一個組合過濾條件,在其構造函數中,ZoneAvoidancePredicate為主過濾條件,AvailabilityPredicate為次過濾條件初始化了組合過濾條件的實例。綜合判斷server所在的區域性能和server可用性輪詢選擇server,并判斷AWS zone的運行性能是否可用,剔除不可用的區域中的server。
自定義負載均衡器
自定義負載均衡器需要實現AbstractLoadBalancerRule類
public class CustomerDefinieIpHashRule extends AbstractLoadBalancerRule {
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
//....
}
public Server choose(ILoadBalancer lb, Object key) {
if(lb==null){
return null;
}
Server server=null;
while(server==null){
//表示啟動的服務列表.(默認情況下單純只用Ribbon時,不會對目標服務做心跳檢測)
List<Server> upList=lb.getReachableServers();
List<Server> allList=lb.getAllServers();
int serverCount=upList.size();
if(serverCount==0){
return null;
}
int index=ipAddressHash(serverCount);
server=upList.get(index);
}
return server;
}
// ip hash算法
private int ipAddressHash(int serverCount){
ServletRequestAttributes requestAttributes= (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
String remoteAddr=requestAttributes.getRequest().getRemoteAddr();
int code=Math.abs(remoteAddr.hashCode());
return code%serverCount;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(),key);
}
}
- 配置文件
goods-service.ribbon.NFLoadBalancerRuleClassName=cn.train.CustomerDefinieIpHashRule
原文鏈接:https://blog.csdn.net/yu0_zhang0/article/details/124511181
相關推薦
- 2022-07-09 利用go語言判斷是否是完全二叉樹_Golang
- 2022-06-02 Kubernetes關鍵組件與結構組成介紹_云和虛擬化
- 2022-12-28 React+Electron快速創建并打包成桌面應用的實例代碼_React
- 2023-05-03 python?re.match函數的具體使用_python
- 2022-07-13 redis搭建哨兵集群的實現步驟_Redis
- 2022-01-29 fastadmin添加追加字段
- 2022-06-02 深入解析Apache?Hudi內核文件標記機制_服務器其它
- 2024-03-19 maven本地倉庫有包,導致could not find artifact
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支