微服務(三) Eureka註冊中心和Ribbon負載均衡

1. Eureka註冊中心

1.1 Eureka的結構和作用

在上一篇文章中 微服務(二)服務拆分及遠程調用

  • order-service在發起遠程調用的時候,該如何得知user-service實例的ip地址和埠?
  • 有多個user-service實例地址,order-service調用時該如何選擇?
  • order-service如何得知某個user-service實例是否依然健康,是不是已經宕機?

這些問題都需要利用SpringCloud中的註冊中心來解決,其中最廣為人知的註冊中心就是Eureka,其結構如下:

問題1:order-service如何得知user-service實例地址?

獲取地址資訊的流程如下:

  • user-service服務實例啟動後,將自己的資訊註冊到eureka-server(Eureka服務端)。這個叫服務註冊
  • eureka-server保存服務名稱到服務實例地址列表的映射關係
  • order-service根據服務名稱,拉取實例地址列表。這個叫服務發現或服務拉取

問題2:order-service如何從多個user-service實例中選擇具體的實例?

  • order-service從實例列表中利用負載均衡演算法選中一個實例地址
  • 向該實例地址發起遠程調用

問題3:order-service如何得知某個user-service實例是否依然健康,是不是已經宕機?

  • user-service會每隔一段時間(默認30秒)向eureka-server發起請求,報告自己狀態,稱為心跳
  • 當超過一定時間沒有發送心跳時,eureka-server會認為微服務實例故障,將該實例從服務列表中剔除
  • order-service拉取服務時,就能將故障實例排除了

注意:一個微服務,既可以是服務提供者,又可以是服務消費者,因此eureka將服務註冊、服務發現等功能統一封裝到了eureka-client端

接下來的步驟

1.2 搭建eureka-server

首先註冊中心服務端:eureka-server,這必須是一個獨立的微服務

1.2.1 創建eureka-server子模組

1.2.2 pom文件

引入SpringCloud為eureka提供的starter依賴:

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

1.2.3 創建主啟動類

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

1.2.4 yml文件

server:
  port: 8090
spring:
  application:
    name: eurekaServer

eureka:
  client:
    service-url:
      defaultZone: //127.0.0.1:8090/eureka

1.2.5 啟動服務

啟動服務然後訪問//127.0.0.1:8090

1.3 服務註冊

在user-service中引入

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

user-service中,修改application.yml文件,添加服務名稱、eureka地址:

spring:
 application:
   name: userservice
eureka:
 client:
   service-url:
     defaultZone: //127.0.0.1:8090/eureka

1.4 啟動多個user-service實例

1.5 服務發現

我們將order-service的邏輯修改:向eureka-server拉取user-service的資訊,實現服務發現。

服務發現也需要知道eureka地址,因此第二步與服務註冊一致,都是配置eureka資訊:
在order-service中,修改application.yml文件,添加服務名稱、eureka地址:

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
spring:
  application:
    name: orderservice
eureka:
  client:
    service-url:
      defaultZone: //127.0.0.1:8090/eureka

1.6 服務拉取和負載均衡

給RestTemplate這個Bean添加一個@LoadBalanced註解:

用服務名代替ip、埠:

2. Ribbon負載均衡

2.1 負載均衡流程

2.2 負載均衡策略

負載均衡的規則都定義在IRule介面中,而IRule有很多不同的實現類:

內置負載均衡規則類 規則描述
RoundRobinRule 簡單輪詢服務列表來選擇伺服器。它是Ribbon默認的負載均衡規則。
AvailabilityFilteringRule 對以下兩種伺服器進行忽略: (1)在默認情況下,這台伺服器如果3次連接失敗,這台伺服器就會被設置為「短路」狀態。短路狀態將持續30秒,如果再次連接失敗,短路的持續時間就會幾何級地增加。 (2)並發數過高的伺服器。如果一個伺服器的並發連接數過高,配置了AvailabilityFilteringRule規則的客戶端也會將其忽略。並發連接數的上限,可以由客戶端的..ActiveConnectionsLimit屬性進行配置。
WeightedResponseTimeRule 為每一個伺服器賦予一個權重值。伺服器響應時間越長,這個伺服器的權重就越小。這個規則會隨機選擇伺服器,這個權重值會影響伺服器的選擇。
ZoneAvoidanceRule 以區域可用的伺服器為基礎進行伺服器的選擇。使用Zone對伺服器進行分類,這個Zone可以理解為一個機房、一個機架等。而後再對Zone內的多個服務做輪詢。
BestAvailableRule 忽略那些短路的伺服器,並選擇並發數較低的伺服器。
RandomRule 隨機選擇一個可用的伺服器。
RetryRule 重試機制的選擇邏輯

默認的實現就是ZoneAvoidanceRule,是一種輪詢方案

2.3 自定義負載均衡策略

注意**,一般用默認的負載均衡規則,不做修改。

2.3.飢餓載入

Ribbon默認是採用懶載入,即第一次訪問時才會去創建LoadBalanceClient,請求時間會很長。

而飢餓載入則會在項目啟動時創建,降低第一次訪問的耗時,通過下面配置開啟飢餓載入:

ribbon:
  eager-load:
    enabled: true
    clients: userservice