文章目錄
- 前言
- 一、Ribbon核心概念
- 二、服務器端負載均衡和Riboon客戶端負載均衡
- 1、服務器端負載均衡:
- 2、Riboon客戶端負載均衡:
- 三、Ribbon策略
- 四、Ribbon配置使用
- 五、配置自定義的負載均衡演算法
- 1、按照權重實作負載均衡
- 1.1 配置Ribbon
- 1.2 全域的負載均衡演算法類
- 1.3 自定義權重實作負載均衡
- 1.4 設定Nacos服務實體權重比例
- 1.4 測驗負載均衡
- 六、Ribbon常用配置
- 總結
前言
Spring Cloud Ribbon是一個基于HTTP和TCP的客戶端負載均衡工具,它基于Netflix Ribbon實作,
一、Ribbon核心概念
Raibbon是基于Netflix Ribbon實作的一套客戶端負載均衡工具,Raibbon客戶端提供了一系列的配置,如超時、重試、負載均衡等,對Spring Cloud Ribbon的理解和使用,對于我們使用Spring Cloud來構建微服務非常重要,比如微服務之間的呼叫,API網關的轉發請求等,實際上都是通過Ribbon來完成的,
通俗的來說:Ribbon = 負載均衡 + RestTemplate
這里提到了一個詞,叫做客戶端負載均衡,那么可能會想到我們的Nginx,那么Nginx是客戶端負載均衡嗎?不是,Nginx實際上是一種集中式負載均衡(服務器端負載均衡),并不屬于客戶端負載均衡范疇,那么這兩者的區別是什么呢?
二、服務器端負載均衡和Riboon客戶端負載均衡
1、服務器端負載均衡:
服務端負載均衡又分為兩種,一種是硬體負載均衡,還有一種是軟體負載均衡,
例如Nginx,是軟體負載均衡,通過Nginx進行負載均衡,先發送請求,然后通過負載均衡演算法,在多個服務器之間選擇一個進行訪問;即在服務器端再進行負載均衡演算法分配,我們來看一張圖,使用Nginx做的負載均衡策略,

2、Riboon客戶端負載均衡:
例如spring cloud中的ribbon,客戶端會有一個服務器地址串列,在發送請求前通過負載均衡演算法選擇一個服務器,然后進行訪問,這是客戶端負載均衡;即在客戶端就進行負載均衡演算法分配,來直接上圖,下圖所示是我們本篇文章要實作的Ribbon負載均衡策略,

三、Ribbon策略
當我們在 RestTemplate 上添加 @LoadBalanced 注解后,就可以用服務名稱來呼叫介面了,當有多個服務的時候,還能做負載均衡,然而Ribbon客戶端組件提供一系列完善的配置項,如連接超時,重試等,并且我們還能夠使用Ribbon實作自定義的負載均衡策略,
負載均衡常用策略方式:
- 默認為輪訓的策略方式
- 隨機
- 重試(如果獲取服務失敗,在指定時間內進行重試,獲取可用服務)
- 過濾掉出故障的服務,選擇一個最小并發量的服務

如下圖為負載均衡輪訓演算法的實作:

四、Ribbon配置使用
這里我們使用Nacos作為注冊中心,模擬訂單服務于庫存服務之間的呼叫,使用Ribbon作為客戶端的負載均衡實作,他的配置方式很簡單,下面我們就搭建好以下三個服務,準備實操一波,
| 服務名稱 | 埠號 |
|---|---|
| dt-stock-service | 8083 |
| dt-stock-service | 8082 |
| dt-order-service | 8081 |
這里我們的庫存服務為兩個,訂單服務為一個,通過訂單服務呼叫庫存服務,實作Ribbon的負載均衡,首先是訂單服務啟動類,我們把RestTemplate 注冊進來,這里我們使用RestTemplate 來實作服務之間的呼叫,RestTemplate 只需要加上 @LoadBalanced 注解后,就可以用服務名稱來呼叫介面了,既能實作Ribbon的負載均衡策略,
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
訂單服務控制器呼叫介面如下:
@RestController
@RequestMapping(value = "order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("test")
public String getOrder() {
String msg = restTemplate.getForObject("http://dt-stock-service/stock/test", String.class);
return "呼叫訂單服務->>>"+msg;
}
}
我們通過服務名稱的方式(dt-stock-service)來呼叫庫存服務介面方法,然后我們再撰寫庫存服務控制器介面方法:
@RestController
@RequestMapping(value = "/stock")
public class StockController {
@Value("${server.port}")
private String port;
@GetMapping("/test")
public String getStock() {
return "呼叫庫存服務:"+port;
}
}
這里我們列印一下當前庫存服務被呼叫的埠,以便觀察Ribbon的負載均衡策略模式,服務架構如下,

我們啟動8081訂單服務,再依次啟動8082、8083庫存服務,服務啟動之后,觀察我們的注冊中心服務實體變化,此時訂單服務有一個實體,庫存服務有兩個實體,服務啟動成功了,下面我們來發送介面測驗:

發送請求:http://localhost:8081/order/test
第一次8083埠:

第二次8082埠:

一直發送介面請求測驗,可以發現,都是8083和8082之間輪訓切換呼叫,那就明白了,Ribbon默認的策略模式是輪詢的方式,在文章開頭我們說過Riboon的策略方式不止輪詢,輪詢只是它自身內部一種默認的實作方式,下面我們就來研究其他的幾種常見的方式怎么玩?
五、配置自定義的負載均衡演算法
1、按照權重實作負載均衡
Ribbon本身是沒有權重的概念的, 那么如何才能實作代用權重的負載均衡呢? 我們在nacos中, 服務器的集群有一個權重的概念, 當給服務器設定了權重, 那么流量就可以根據權重比例分配到服務器上,
1.1 配置Ribbon
spring:
application:
name: dt-order-service
cloud:
nacos:
server-addr: 47.108.191.196:9091
discovery:
username: nacos
password: nacos
namespace: public
ribbon:
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #指定全域的負載均衡演算法
eager-load:
enabled: true #開啟饑餓模式
clients: dt-stock-service #為哪些服務的名稱開啟饑餓加載,多個用逗號分隔
com.dt.springcloud.ribbon.config.GlobalRibbonConfig #指定全域的負載均衡演算法類名
這里小編解釋一下Ribbon為什么會有饑餓模式的配置:ribbon客戶端不是在服務啟動的時候加載的,所以可能第一次呼叫會很慢,甚至超時,
1.2 全域的負載均衡演算法類
/**
* 全域設定自定義的權重負載均衡策略
* @author DT
* @date 2021/8/7 20:39
*/
@Configuration
public class GlobalRibbonConfig {
@Bean
public IRule getRule() {
// 實作帶有權重的負載均衡策略
return new MyWeightRule();
}
}
1.3 自定義權重實作負載均衡
/**
* 自定義一個權重負載均衡策略
* @author DT
* @date 2021/8/7 20:32
*/
public class MyWeightRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties discoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) { }
/**
* 自定義實作負載均衡策略的方法
*/
@Override
public Server choose(Object key) {
try {
// 呼叫父類方法, 獲取當前使用的負載均衡器
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
// 獲取當前服務的名稱
String serviceName = baseLoadBalancer.getName();
// 獲取nacos的服務發現API
NamingService namingService = discoveryProperties.namingServiceInstance();
// nacos實作了權重的負載均衡演算法
Instance instance = namingService.selectOneHealthyInstance(serviceName);
// 列印輸出
String threadName = Thread.currentThread().getName();
System.out.println("執行緒->>>" + threadName + "->>>發送請求");
System.out.println("IP埠->>>"+instance.getIp()+":"+instance.getPort());
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
}
return null;
}
}
1.4 設定Nacos服務實體權重比例


我們一個設定為0.3, 另一個設定成0.7, 也就是說如果有10次請求, 基本上都是會打到8082埠上的,因為8082的權重最高,打到它的介面數量應該是最多的,
1.4 測驗負載均衡
http://localhost:8081/order/test

觸發10次請求,基本7次左右都會打到8082服務上面,
六、Ribbon常用配置
ribbon:
ConnectTimeout: 1000 #服務請求連接超時時間(毫秒)
ReadTimeout: 3000 #服務請求處理超時時間(毫秒)
OkToRetryOnAllOperations: true #對超時請求啟用重試機制
MaxAutoRetriesNextServer: 1 #切換重試實體的最大個數
MaxAutoRetries: 1 #切換實體后重試最大次數
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #修改負載均衡演算法
在我們文章當中,使用的是全域配置,當然你也可以指定針對單獨的服務配置:
#服務名
dt-order-service:
ribbon:
ConnectTimeout: 1000 #服務請求連接超時時間(毫秒)
ReadTimeout: 3000 #服務請求處理超時時間(毫秒)
OkToRetryOnAllOperations: true #對超時請求啟用重試機制
MaxAutoRetriesNextServer: 1 #切換重試實體的最大個數
MaxAutoRetries: 1 #切換實體后重試最大次數
NFLoadBalancerRuleClassName: com.dt.springcloud.ribbon.config.GlobalRibbonConfig #修改負載均衡演算法
總結
好了,以上內容就是今天的輸出,后面我們再繼續深入研究微服務其他的組件的使用以及原理剖析,創作不易,喜歡的請關注小編CSDN:https://blog.csdn.net/qq_41107231 以及掘金:https://juejin.cn/user/3940246036699848
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/292675.html
標籤:其他
