05-LoadBalancer負載均衡

长名06發表於2024-10-01

1.Ribbon目前也進入維護模式

1.1 Ribbon介紹

Spring Cloud Ribbon是基於Netflix Ribbon實現的一套客戶端負載均衡的工具。

簡單的說,Ribbon是Netflix釋出的開源專案,主要功能是提供客戶端的軟體負載均衡演算法和服務呼叫。Ribbon客戶端元件提供一系列完善的配置項如連線超時,重試等。簡單的說,就是在配置檔案中列出Load Balancer(簡稱LB)後面所有的機器,Ribbon會自動的幫助你基於某種規則(如簡單輪詢,隨機連線等)去連線這些機器。我們很容易使用Ribbon實現自定義的負載均衡演算法。

https://github.com/Netflix/ribbon

1.2 Ribbon替代方案


spring-cloud-loadbalancer

2.spring-cloud-loadbalancer概述

2.1 官網

2.2 是什麼

LB負載均衡(Load Balance)是什麼

簡單的說就是將使用者的請求平攤的分配到多個服務上,從而達到系統的HA(高可用),常見的負載均衡有軟體NginxLVS,硬體F5

spring-cloud-starter-loadbalancer元件是什麼

Spring Cloud LoadBalancer是由SpringCloud官方提供的一個開源的、簡單易用的客戶端負載均衡器,它包含在SpringCloud-commons中用它來替換了以前的Ribbon元件。相比較於Ribbon,SpringCloud LoadBalancer不僅能夠支援RestTemplate,還支援WebClient(WeClient是Spring Web Flux中提供的功能,可以實現響應式非同步請求)。

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html

2.3 面試題

loadbalancer本地負載均衡客戶端 VS Nginx服務端負載均衡區別

Nginx是伺服器負載均衡,客戶端所有請求都會交給nginx,然後由nginx實現轉發請求,即負載均衡是由服務端實現的。

loadbalancer本地負載均衡,在呼叫微服務介面時候,會在註冊中心上獲取註冊資訊服務列表之後快取到JVM本地,從而在本地實現RPC遠端服務呼叫技術。

個人理解,客戶端負載均衡,是由客戶端,選擇向那臺機器發起請求,並獲得響應。而服務端負載均衡,是由伺服器端(nginx),決定某個請求,由那臺機器處理,然後響應給客戶端。

3.spring-cloud-loadbalancer負載均衡解析

3.1 理論


LoadBalancer 在工作時分成兩步:

第一步,先選擇ConsulServer從服務端查詢並拉取服務列表,知道了它有多個服務(上圖3個服務),這3個實現是完全一樣的,

預設輪詢呼叫誰都可以正常執行。類似生活中求醫掛號,某個科室今日出診的全部醫生,客戶端你自己選一個。

第二步,按照指定的負載均衡策略從server取到的服務註冊列表中由客戶端自己選擇一個地址,所以LoadBalancer是一個客戶端的負載均衡器。

3.2 實操

3.2.1 官網參考如何正確使用

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html


3.2.2 按照8001複製新建8002

3.2.3 啟動Consul,然後啟動8001和8002

啟動Consul

consul agent -dev

獲取在consul中配置的測試資訊,透過8001或8002介面

bug

在consul中的配置重啟後,消失了

3.2.4 Consul資料持久化配置並註冊為Window服務

1.在consul.exe的同級目錄下,新建mydata資料夾

2.新建consul_start.bat檔案

@echo.Consul Start......  
@echo off  
@sc create Consul binpath= "D:\Develop\consul\consul.exe agent -server -ui -bind=127.0.0.1 -client=0.0.0.0 -bootstrap-expect  1  -data-dir D:\Develop\consul\mydata   "
@net start Consul
@sc config Consul start= AUTO  
@echo.Consul start is OK......success
@pause

3.管理員許可權開啟

4.啟動結果

5.win後臺

會多出consul服務

6.後續consul的配置資料會儲存到mydata資料夾

3.2.5 修改Order模組

1.引入依賴

<!--loadbalancer-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2.新增介面

@GetMapping(value = "/consumer/pay/get/info")
public  String getInfoByConsul() {
    return restTemplate.getForObject(PAYMENT_SRV_URL + "/pay/get/info", String.class);
}

3.consul服務


4.測試

http://localhost:8080/consumer/pay/get/info

訪問改介面,可見交替訪問8001和8002

3.3 小總結

3.3.1 使用DiscoveryClient動態獲取上線的服務列表

3.3.2 訂單模組新增程式碼
@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/discovery")
public String discovery() {
    //獲取所有的consul中的服務名
    List<String> services = discoveryClient.getServices();
    for (String element : services) {
        System.out.println(element);
    }
    System.out.println("===================================");
	//獲取key服務的所有服務例項
    List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
    for (ServiceInstance element : instances) {
        //服務例項名 + 服務主機名 + 服務埠號 + 服務url
        System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t" + element.getUri());
    }

    return instances.get(0).getServiceId() + ":" + instances.get(0).getPort();
}

輸出資訊

cloud-consumer-order
cloud-payment-service
consul
===================================
cloud-payment-service	x	8001	http://x:8001 x是主機名
cloud-payment-service	x	8002 	http://x:8002

3.3.3 負載均衡原理小總結

負載均衡演算法:rest介面第幾次請求數 % 伺服器叢集總數量 = 實際呼叫伺服器位置下標 ,每次服務重啟動後rest介面計數從1開始。

List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
//如
List [0] instances = 127.0.0.1:8002
List [1] instances = 127.0.0.1:8001

8001+ 8002 組合成為叢集,它們共計2臺機器,叢集總數為2, 按照輪詢演算法原理:

當總請求數為1時: 1 % 2 =1 對應下標位置為1 ,則獲得服務地址為127.0.0.1:8001

當總請求數位2時: 2 % 2 =0 對應下標位置為0 ,則獲得服務地址為127.0.0.1:8002

當總請求數位3時: 3 % 2 =1 對應下標位置為1 ,則獲得服務地址為127.0.0.1:8001

當總請求數位4時: 4 % 2 =0 對應下標位置為0 ,則獲得服務地址為127.0.0.1:8002

如此類推......

4.負載均衡演算法原理

4.1 預設演算法,有幾種

4.1.1 官網

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/loadbalancer.html#switching-between-the-load-balancing-algorithms

4.1.2 預設兩種


輪詢

public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer

隨機

public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer 

原始碼

略,見org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer介面

4.2 演算法切換

@LoadBalancerClient(value = "cloud-payment-service",configuration = RestTemplateConfig.class)
public class RestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment,
                                                            LoadBalancerClientFactory loadBalancerClientFactory) {
        String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
        return new RandomLoadBalancer(loadBalancerClientFactory
                .getLazyProvider(name, ServiceInstanceListSupplier.class),
                name);
    }

}

The classes you pass as @LoadBalancerClient or @LoadBalancerClients configuration arguments should either not be annotated with @Configuration or be outside component scan scope.

在RestTemplateConfig的類上,有@LoadBalancerClient或者@LoadBalancerClients,就不該在使用@Configuration註解了,包含了。

Configuration(proxyBeanMethods = false)
@Import(LoadBalancerClientConfigurationRegistrar.class)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LoadBalancerClient 
@Configuration(proxyBeanMethods = false)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Documented
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients

只是為了記錄自己的學習歷程,且本人水平有限,不對之處,請指正。

相關文章