天天看點

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

前言

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

本文為 微服務負載均衡器Ribbon與LoadBalancer 相關知識,下邊将對

什麼是Ribbon

(包括:

用戶端的負載均衡

服務端的負載均衡

常見負載均衡算法

),

Nacos使用Ribbon

Ribbon核心原理

(包括:

Ribbon原理

Ribbon負載均衡政策

饑餓加載

),

Spring Cloud LoadBalancer

(包括:

什麼是Spring Cloud LoadBalancer

RestTemplate整合LoadBalancer

)等進行詳盡介紹~

📌部落客首頁:小新要變強 的首頁

👉Java全棧學習路線可參考:【Java全棧學習路線】最全的Java學習路線及知識清單,Java自學方向指引,内含最全Java全棧學習技術清單~

👉算法刷題路線可參考:算法刷題路線總結與相關資料分享,内含最詳盡的算法刷題路線指南及相關資料分享~

👉Java微服務開源項目可參考:企業級Java微服務開源項目(開源架構,用于學習、畢設、公司項目、私活等,減少開發工作,讓您隻關注業務!)

↩️本文上接:Spring Cloud Alibaba全家桶(二)——微服務元件Nacos注冊中心

目錄

微服務負載均衡器Ribbon與LoadBalancer

  • 前言
  • 目錄
  • 一、什麼是Ribbon
    • 1️⃣用戶端的負載均衡
    • 2️⃣服務端的負載均衡
    • 3️⃣常見負載均衡算法
  • 二、Nacos使用Ribbon
  • 三、Ribbon核心原理
    • 1️⃣Ribbon原理
    • 2️⃣Ribbon負載均衡政策
    • 3️⃣饑餓加載
  • 四、Spring Cloud LoadBalancer
    • 1️⃣什麼是Spring Cloud LoadBalancer
    • 2️⃣RestTemplate整合LoadBalancer
  • 後記
Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

一、什麼是Ribbon

目前主流的負載方案分為以下兩種:

  • 集中式負載均衡,在消費者和服務提供方中間使用獨立的代理方式進行負載,有硬體的(比如 F5),也有軟體的(比如Nginx)。
  • 用戶端根據自己的請求情況做負載均衡,Ribbon 就屬于用戶端自己做負載均衡。

Spring Cloud Ribbon是基于Netflix Ribbon 實作的一套用戶端的負載均衡工具,Ribbon用戶端元件提供一系列的完善的配置,如逾時,重試等。通過Load Balancer擷取到服務提供的所有機器執行個體,Ribbon會自動基于某種規則(輪詢,随機)去調用這些服務。Ribbon也可以實作我們自己的負載均衡算法。

1️⃣用戶端的負載均衡

例如spring cloud中的ribbon,用戶端會有一個伺服器位址清單,在發送請求前通過負載均衡算法選擇一個伺服器,然後進行通路,這是用戶端負載均衡;即在用戶端就進行負載均衡算法配置設定。

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

2️⃣服務端的負載均衡

例如Nginx,通過Nginx進行負載均衡,先發送請求,然後通過負載均衡算法,在多個伺服器之間選擇一個進行通路;即在伺服器端再進行負載均衡算法配置設定。

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

3️⃣常見負載均衡算法

  • 随機,通過随機選擇服務進行執行,一般這種方式使用較少;
  • 輪訓,負載均衡預設實作方式,請求來之後排隊處理;
  • 權重輪訓,通過對伺服器性能的分型,給高配置,低負載的伺服器配置設定更高的權重,均衡各個伺服器的壓力;
  • 位址Hash,通過用戶端請求的位址的HASH值取模映射進行伺服器排程。 ip —>hash
  • 最小連結數,即使請求均衡了,壓力不一定會均衡,最小連接配接數法就是根據伺服器的情況,比如請求積壓數等參數,将請求配置設定到目前壓力最小的伺服器上。

    最小活躍數

二、Nacos使用Ribbon

🍀(1)引入依賴

nacos-discovery依賴了ribbon,可以不用再引入ribbon依賴。

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

🍀(2) 添加@LoadBalanced注解

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

🍀(3)修改controller

@Autowired
private RestTemplate restTemplate;

@RequestMapping(value = "/findOrderByUserId/{id}")
public R findOrderByUserId(@PathVariable("id") Integer id) {
  // RestTemplate調用
  //String url = "http://localhost:8020/order/findOrderByUserId/"+id;
  //模拟ribbon實作
  //String url = getUri("mall‐order")+"/order/findOrderByUserId/"+id;
  // 添加@LoadBalanced
  String url = "http://mall‐order/order/findOrderByUserId/"+id;
  R result = restTemplate.getForObject(url,R.class);

  return result;
}
           

三、Ribbon核心原理

1️⃣Ribbon原理

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

2️⃣Ribbon負載均衡政策

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

IRule

這是所有負載均衡政策的父接口,裡邊的核心方法就是choose方法,用來選擇一個服務執行個體。

AbstractLoadBalancerRule

AbstractLoadBalancerRule是一個抽象類,裡邊主要定義了一個ILoadBalancer,這裡定義它的目的主要是輔助負責均衡政策選取合适的服務端執行個體。

  • RandomRule

看名字就知道,這種負載均衡政策就是随機選擇一個服務執行個體,看源碼我們知道,在RandomRule的無參構造方法中初始化了一個Random對象,然後在它重寫的choose方法又調用了choose(ILoadBalancer lb, Object key)這個重載的choose方法,在這個重載的choose方法中,每次利用random對象生成一個不大于服務執行個體總數的随機數,并将該數作為下标是以擷取一個服務執行個體。

  • RoundRobinRule

RoundRobinRule這種負載均衡政策叫做線性輪詢負載均衡政策。這個類的choose(ILoadBalancer lb, Object key)函數整體邏輯是這樣的:開啟一個計數器count,在while循環中周遊服務清單,擷取清單之前先通過incrementAndGetModulo方法擷取一個下标,這個下标是一個不斷自增長的數先加1然後和服務清單總數取模之後擷取到的(是以這個下标從來不會越界),拿着下标再去服務清單清單中取服務,每次循環計數器都會加1,如果連續10次都沒有取到服務,則會報一個警告No available alive servers after 10 tries from load balancer: XXXX。

  • RetryRule(在輪詢的基礎上進行重試)

看名字就知道這種負載均衡政策帶有重試功能。首先RetryRule中又定義了一個subRule,它的實作類是RoundRobinRule,然後在RetryRule的choose(ILoadBalancer lb, Object key)方法中,每次還是采用RoundRobinRule中的choose規則來選擇一個服務執行個體,如果選到的執行個體正常就傳回,如果選擇的服務執行個體為null或者已經失效,則在失效時間deadline之前不斷的進行重試(重試時擷取服務的政策還是RoundRobinRule中定義的政策),如果超過了deadline還是沒取到則會傳回一個null。

  • WeightedResponseTimeRule(權重 —nacos的NacosRule ,Nacos還擴充了一個自己的基于配置的權重擴充)

WeightedResponseTimeRule是RoundRobinRule的一個子類,在WeightedResponseTimeRule中對RoundRobinRule的功能進行了擴充,WeightedResponseTimeRule中會根據每一個執行個體的運作情況來給計算出該執行個體的一個權重,然後在挑選執行個體的時候則根據權重進行挑選,這樣能夠實作更優的執行個體調用。WeightedResponseTimeRule中有一個名叫DynamicServerWeightTask的定時任務,預設情況下每隔30秒會計算一次各個服務執行個體的權重,權重的計算規則也很簡單,如果一個服務的平均響應時間越短則權重越大,那麼該服務執行個體被選中執行任務的機率也就越大。

  • ClientConfigEnabledRoundRobinRule

ClientConfigEnabledRoundRobinRule選擇政策的實作很簡單,内部定義了RoundRobinRule,choose方法還是采用了RoundRobinRule的choose方法,是以它的選擇政策和RoundRobinRule的選擇政策一緻,不贅述。

  • BestAvailableRule

BestAvailableRule繼承自ClientConfigEnabledRoundRobinRule,它在ClientConfigEnabledRoundRobinRule的基礎上主要增加了根據loadBalancerStats中儲存的服務執行個體的狀态資訊來過濾掉失效的服務執行個體的功能,然後順便找出并發請求最小的服務執行個體來使用。然而loadBalancerStats有可能為null,如果loadBalancerStats為null,則BestAvailableRule将采用它的父類即ClientConfigEnabledRoundRobinRule的服務選取政策(線性輪詢)。

  • ZoneAvoidanceRule (預設規則,複合判斷server所在區域的性能和server的可用性選擇伺服器。)

ZoneAvoidanceRule是PredicateBasedRule的一個實作類,隻不過這裡多一個過濾條件,ZoneAvoidanceRule中的過濾條件是以ZoneAvoidancePredicate為主過濾條件和以AvailabilityPredicate為次過濾條件組成的一個叫做CompositePredicate的組合過濾條件,過濾成功之後,繼續采用線性輪詢(RoundRobinRule)的方式從過濾結果中選擇一個出來。

  • AvailabilityFilteringRule(先過濾掉故障執行個體,再選擇并發較小的執行個體)

過濾掉一直連接配接失敗的被标記為circuit tripped的後端Server,并過濾掉那些高并發的後端Server或者使用一個AvailabilityPredicate來包含過濾server的邏輯,其實就是檢查status裡記錄的各個Server的運作狀态。

🍀(1)修改預設負載均衡政策

(1)配置類:

@Configuration
public class RibbonConfig {

  /**
  * 全局配置
  * 指定負載均衡政策
  * @return
  */
  @Bean
  public IRule iRule() {
    // 指定使用Nacos提供的負載均衡政策(優先調用同一叢集的執行個體,基于随機權重)
    return new NacosRule();
  }
}
           

注意: 此處有坑。不能寫在@SpringbootApplication注解的@CompentScan掃描得到的地方,否則自定義的配置類就會被所有的RibbonClients共享。 不建議這麼使用,推薦yml方式

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記
Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

利用@RibbonClient指定微服務及其負載均衡政策。

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})
//@RibbonClient(name = "mall‐order",configuration = RibbonConfig.class)
//配置多個 RibbonConfig不能被@SpringbootApplication的@CompentScan掃描到,否則就是全局配置的效果
@RibbonClients(value = {
  // 在SpringBoot主程式掃描的包外定義配置類
  @RibbonClient(name = "mall‐order",configuration = RibbonConfig.class),
  @RibbonClient(name = "mall‐account",configuration = RibbonConfig.class)
})
public class MallUserRibbonDemoApplication {

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

配置檔案: 調用指定微服務提供的服務時,使用對應的負載均衡算法

修改application.yml:

# 被調用的微服務名
mall‐order:
  ribbon:
  # 指定使用Nacos提供的負載均衡政策(優先調用同一叢集的執行個體,基于随機&權重)
  NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
           

🍀(2)自定義負載均衡政策

通過實作 IRule 接口可以自定義負載政策,主要的選擇服務邏輯在 choose 方法中。

(1)實作基于Nacos權重的負載均衡政策

@Slf4j
public class NacosRandomWithWeightRule extends AbstractLoadBalancerRule {

  @Autowired
  private NacosDiscoveryProperties nacosDiscoveryProperties;

  @Override
  public Server choose(Object key) {
    DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer) getLoadBalancer();
    String serviceName = loadBalancer.getName();
    NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
    try {
      //nacos基于權重的算法
      Instance instance = namingService.selectOneHealthyInstance(serviceName);
      return new NacosServer(instance);
    } catch (NacosException e) {
      log.error("擷取服務執行個體異常:{}", e.getMessage());
      e.printStackTrace();
    }
    return null;
  }
  @Override
  public void initWithNiwsConfig(IClientConfig clientConfig) {

  }
}
           

(2)配置自定義的政策

修改application.yml:

# 被調用的微服務名
mall‐order:
  ribbon:
  # 自定義的負載均衡政策(基于随機&權重)
  NFLoadBalancerRuleClassName: com.tuling.mall.ribbondemo.rule.NacosRandomWithWeightRule
           

3️⃣饑餓加載

在進行服務調用的時候,如果網絡情況不好,第一次調用會逾時。

Ribbon預設懶加載,意味着隻有在發起調用的時候才會建立用戶端。

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

開啟饑餓加載,解決第一次調用慢的問題:

ribbon:
  eager‐load:
    # 開啟ribbon饑餓加載
    enabled: true
    # 配置mall‐user使用ribbon饑餓加載,多個使用逗号分隔
    clients: mall‐order
           

源碼對應屬性配置類:RibbonEagerLoadProperties

測試:

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

四、Spring Cloud LoadBalancer

1️⃣什麼是Spring Cloud LoadBalancer

Spring Cloud LoadBalancer是Spring Cloud官方自己提供的用戶端負載均衡器, 用來替代Ribbon。

Spring官方提供了兩種負載均衡的用戶端:

  • RestTemplate: RestTemplate是Spring提供的用于通路Rest服務的用戶端,RestTemplate提供了多種便捷通路遠端Http服務的方法,能夠大大提高用戶端的編寫效率。預設情況下,RestTemplate預設依賴jdk的HTTP連接配接工具。
  • WebClient: WebClient是從Spring WebFlux 5.0版本開始提供的一個非阻塞的基于響應式程式設計的進行Http請求的用戶端工具。它的響應式程式設計的基于Reactor的。WebClient中提供了标準Http請求方式對應的get、post、put、delete等方法,可以用來發起相應的請求。

2️⃣RestTemplate整合LoadBalancer

🍀(1)引入依賴

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

<!‐‐ 提供了RestTemplate支援 ‐‐>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring‐boot‐starter‐web</artifactId>
</dependency>

<!‐‐ nacos服務注冊與發現 移除ribbon支援‐‐>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring‐cloud‐starter‐alibaba‐nacos‐discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring‐cloud‐starter‐netflix‐ribbon</artifactId>
</exclusion>
</exclusions>
</dependency>
           

注意: nacos-discovery中引入了ribbon,需要移除ribbon的包;如果不移除,也可以在yml中配置不使用ribbon。

spring:
  application:
    name: mall‐user‐loadbalancer‐demo
  cloud:
    nacos:
      discovery:
      server‐addr: 127.0.0.1:8848
# 不使用ribbon
    loadbalancer:
      ribbon:
        enabled: false
           

原理: 預設情況下,如果同時擁有RibbonLoadBalancerClient和BlockingLoadBalancerClient,為了保持向後相容性,将使用RibbonLoadBalancerClient。要覆寫它,可以設定spring.cloud.loadbalancer.ribbon.enabled屬性為false。

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

🍀(2)使用@LoadBalanced注解配置RestTemplate

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

🍀(3)使用

@RestController
@RequestMapping("/user")
public class UserController {

  @Autowired
  private RestTemplate restTemplate;

  @RequestMapping(value = "/findOrderByUserId/{id}")
  public R findOrderByUserId(@PathVariable("id") Integer id) {
  String url = "http://mall‐order/order/findOrderByUserId/"+id;
  R result = restTemplate.getForObject(url,R.class);
  return result;
  } 
}
           

後記

Spring Cloud Alibaba全家桶(三)——微服務負載均衡器Ribbon與LoadBalancer前言目錄一、什麼是Ribbon二、Nacos使用Ribbon三、Ribbon核心原理四、Spring Cloud LoadBalancer後記

👉Java全棧學習路線可參考:【Java全棧學習路線】最全的Java學習路線及知識清單,Java自學方向指引,内含最全Java全棧學習技術清單~

👉算法刷題路線可參考:算法刷題路線總結與相關資料分享,内含最詳盡的算法刷題路線指南及相關資料分享~

繼續閱讀