Spring Cloud Ribbon---微服務調用和客戶端負載均衡


前面分析了Eureka的使用,作為服務注冊中心,Eureka 分為 Server 端和 Client 端,Client 端作為服務的提供者,將自己注冊到 Server 端,Client端高可用的方式是使用多機部署然后注冊到Server,Server端為了保證服務的高可用,也可以使用多機部署的方式。前面簡單搭建了Eureka Client 和 Server,然后將Client成功注冊到 Server,本節我們將來看看如何調用Eureka服務,在多機部署情況下如何保證負載均衡。Spring Cloud 提供了一個組件:Ribbon。

Ribbon是客戶端負載均衡器,可以對HTTP和TCP客戶端的行為進行大量控制。Ribbon中的中心概念是指定客戶端的概念。

關於服務的負載均衡,硬要是分的話可以分兩種:

  1. 服務端負載均衡。將多個服務注冊到一個公共的注冊中心,服務調用者訪問注冊中心,由注冊中心提供服務的負載均衡。
  2. 客戶端負載均衡。將多個服務注冊到一個注冊中心,注冊中心維護一個注冊表,如果有另一個服務想要調用這個服務,那么訪問注冊中心即可,注冊中心返回注冊表信息給服務端,服務端通過特定的平衡算法來決定要調用注冊表中的哪個提供者。

服務端負載均衡:

客戶端負載均衡:

服務端負載均衡的代表性例子就是nginx,LVS。那么客戶端的負載均衡就是我們要說的Ribbon。Ribbon主要提供客戶端負載平衡算法,除此之外,Ribbon還提供:

  • 服務發現集成 :功能區負載平衡器在動態環境(如雲)中提供服務發現。功能區庫中包含與Eureka和Netflix服務發現組件的集成;
  • 容錯 : Ribbon API可以動態確定服務器是否已在實時環境中啟動並運行,並且可以檢測到那些已關閉的服務器;
  • 可配置的負載平衡規則 : Ribbon支持開箱即用的RoundRobinRuleAvailabilityFilteringRuleWeightedResponseTimeRule,還支持定義自定義規則。

Ribbon API提供以下組件供我們使用:

  • Rule :定義負載均衡策略;
  • Ping : 定義如何ping目標服務實例來判斷是否存活, ribbon使用單獨的線程每隔一段時間(默認10s)對本地緩存的ServerList做一次檢查;
  • ServerList :定義如何獲取服務實例列表. 兩種實現基於配置的ConfigurationBasedServerList和基於Eureka服務發現的DiscoveryEnabledNIWSServerList
  • ServerListFilter: 用來使用期望的特征過濾靜態配置動態獲得的候選服務實例列表. 若未提供, 默認使用ZoneAffinityServerListFilter
  • ILoadBalancer: 定義了軟負載均衡器的操作的接口. 一個典型的負載均衡器至少需要一組用來做負載均衡的服務實例, 一個標記某個服務實例不在旋轉中的方法, 和對應的方法調用從實例列表中選出某一個服務實例;
  • ServerListUpdater: DynamicServerListLoadBalancer用來更新實例列表的策略(推EurekaNotificationServerListUpdater/拉PollingServerListUpdater, 默認是拉)

配置服務策略

全局策略設置

使用以下方式配置的策略表示對該項目中調用的所有服務生效。

@Configuration
public class MyConfiguration{
    @Bean
    public IRule ribbonRule(){
        return new RandomRule();
    }
    
    //定義一個負載均衡的RestTemplate
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

}

上面的配置表示:

  1. 定義了一個隨機方式的服務調用方式,即隨即調用某個服務的提供者;
  2. 定義一個負載均衡的 RestTemplate,使用了 @LoadBalanced注解,該注解配合覆蓋均衡策略一起使用 RestTemplate 發出的請求才能生效。

RestTemplate是 Spring 提供的用於訪問Rest服務的客戶端模板工具集,Ribbon並沒有創建新輪子,基於此通過負載均衡配置發出HTTP請求。

ribbon的負載均衡策略主要包括以下幾種:

策略類 命名 描述
RandomRule 隨機策略 隨機選擇server
RoundRobinRule 輪詢策略 按順序選擇server
RetryRule 重試策略 在一個配置時間段內當選擇的server不成功,則繼續輪訓,一直嘗試選擇一個可用的server
BestAvailableRule 最低並發策略 先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,然后選擇一個並發量最小的服務。
AvailabilityFilteringRule 可用過濾策略 先過濾掉由於多次訪問故障而處於斷路器跳閘狀態的服務,以及並發連接數超過閾值的服務,剩下的服務,使用輪詢策略
ResponseTimeWeightedRule 響應時間加權策略 根據server的響應時間分配權重。響應時間越長,權重越低,被選擇到的概略就越低,權重越高,被選擇到的概率就越高
ZoneAvoidanceRule 區域權衡策略 綜合判斷server所在的區域的性能和server的可用性輪詢選擇server,並且判定一個AWS Zobe的運行性能是否可用,提出不可用的Zone中所有server
局部策略設置

如果在項目中你想對某些服務使用指定的負載均衡策略,那么可以如下配置:

@Configuration
@RibbonClients({
        @RibbonClient(name = "user-service",configuration = UserServiceConfig.class),
    	@RibbonClient(name = "order-service",configuration = OrderServiceConfig.class)
})
public class RibbonConfig {
}

@RibbonClients 中可以包含多個@RibbonClient。每個@RibbonClient表示一個服務名,后面對應的類表示該服務配套的策略規則。

如果你只想對一個服務應用某種規則,那么可以省略:@RibbonClients:

@Configuration
@RibbonClient(name = "order-service",configuration = OrderServiceConfig.class)
public class RibbonConfig {
}

超時重試

HTTP請求不免的會有網絡不好的情況出現超時,Ribbon提供了超時重試機制,提供如下參數可以設置:

ribbon-client:
  ribbon:
    ConnectTimeout: 3000
    ReadTimeout: 60000
    MaxAutoRetries: 1 #對第一次請求的服務的重試次數
    MaxAutoRetriesNextServer: 1 #要重試的下一個服務的最大數量(不包括第一個服務)
    OkToRetryOnAllOperations: true
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

飢餓加載

Ribbon在進行客戶端負載均衡的時候並不是在啟動的時候就加載上下文的,實在實際請求的時候才加載,有點像servlet的第一次請求的時候才去生成實例,這回導致第一次請求會比較的緩慢,甚至可能會出現超時的情況。所以我們可以指定具體的客戶端名稱來開啟飢餓加載,即在啟動的時候便加載素養的配置項的應用上下文。

ribbon:
  eager-load:
    enabled: true
    clients: ribbon-client-1, ribbon-client-2, ribbon-client-3

Ribbon負載均衡示例

下面看一下整合Eureka 和 Ribbon如何實現服務調用 和 負載均衡。有了Eureka之后,服務調用就無需關注服務提供者的IP。

服務的整體流程如上圖,一個集成了Ribbon的Eureka Client 從Eureka Server中獲取服務,首先拉取服務list,然后Ribbon服務會根據配置的負載均衡策略選取合適的服務提供者,向該提供者發送請求獲取結果。

工程結構如下:

一個 Eureka Server,3個Eureka Client,一個集成了Ribbon 的Consumer。整體代碼我就不貼了,已經上傳至GitHub自行下載。Demo 工程見這里:

簡單說一下關於 Ribbon consumer的配置:

pom文件中需要引入關於Ribbon的包,同時consumer也是一個Eureka Client要去拉 Eureka Server的配置,所以需要Eureka client的包。

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

在啟動類中初始化了兩個bean:

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class RibbonDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonDemoApplication.class, args);
    }

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

    @Bean
    public IRule ribbonRule() {
        return new RandomRule();//這里配置策略,和配置文件對應
    }
}

RestTemplate 和 IRule負載均衡策略。

然后就可以使用已經配置了負載均衡的 RestTemplate 發起請求了:

@Service
public class DemoService {

    @Autowired
    RestTemplate restTemplate;

    public String hello(String name) {

        return restTemplate.getForEntity("http://eureka-client/hello/" + name, String.class).getBody();
    }
}

大家自行下載Demo工程進行調試。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM