微服務架構 | 3.1 Netflix Eureka 註冊中心

多氯環己烷發表於2022-01-15


前言

參考資料
《Spring Microservices in Action》
《Spring Cloud Alibaba 微服務原理與實戰》
《B站 尚矽谷 SpringCloud 框架開發教程 周陽》
《Spring Cloud Netflix 官方資料》

Eureka 是 Netflix 開發的服務發現框架,本身是一個基於REST的服務,主要用於定位執行在 AWS 域中的中間層服務,以達到負載均衡和中間層服務故障轉移的目的;

Spring Cloud 將它整合在其子專案 spring-cloud-netflix 中,以實現 Spring Cloud 的服務發現功能;


1. Eureka 基礎知識

1.1 Eureka 模型中的伺服器與客戶端

  • 伺服器:服務的註冊中心,負責維護與管理註冊的服務列表;
  • 客戶端:所有要註冊進 Eureka 的服務都稱為 Eureka 的客戶端,它可以是服務配置中心 Spring Cloud Config;也可以是閘道器 zuul;還可以是實際的業務服務等;

1.2 Eureka 的 30s 啟動機制

  • 當客戶端服務通過 Eureka 註冊時, Eureka 將在 30s 內等待 3 次連續的健康檢查,然後才能通過 Eureka 獲取該服務;
  • 每次服務註冊需要 30 s 的時間才能顯示在 Eureka服務中,因為 Eureka需要從服務接收 3 次。連續心跳包 ping,每次心跳包 ping 間隔 10 s,然後才能使用這個服務;

1.3 Eureka 為什麼註冊服務的 IP ,而不是主機名

  • 具體例子詳情可以參考《3.2 修改 boostrap.yml 配置檔案》;
  • 在基於伺服器的環境中時:Eureka 在嘗試註冊客戶端服務時,客戶端服務會被分配一個 DNS 支援的主機名,客戶端服務通過這個 DNS 主機名與外界聯絡;
  • 在基於容器的部署(如 Docker)中:容器以隨機生成的主機名啟動,沒有 DNS 記錄;使用主機名將無法解析;

1.4 Eureka 伺服器的高可用(叢集)

  • 在實際生產中,為了實現 Eureka 的高可用,需要建立多個 Eureka 伺服器以便相互複製登錄檔的內容;
  • 一組 Eureka 登錄檔相互之間使用點對點通訊模型進行通訊;
  • 需要在客戶端 eureka.serviceUrl.defaultZone 屬性中用逗號隔開多個 Eureka 伺服器的位置;
  • 同時,伺服器的 eureka.serviceUrl.defaultZone 屬性中用逗號隔開多個除了自身的 Eureka 伺服器的位置;

2. 構建 Eureka 伺服器

2.1 引入 pom.xml 依賴

<!-- 1.x老版本的依賴 -->
<dependency>  
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- 2.x新版本的依賴 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
  • Eureka 的 Maven 依賴檔案預設包含 Ribbon 元件;
  • 新老版本二選一即可;

2.2 修改 application.yaml 配置檔案

server:
  port: 8761 #Eureka 監聽的埠
spring:
  application:
    name: eureka-server #Eureka 伺服器的名稱
eureka:
  client:
    fetch-registry: false #不要在本地快取登錄檔資訊
    register-with-eureka: false #不使用 Eureka 服務進行註冊
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  instance:
    hostname: localhost
  server:  #配置屬性,但由於 Eureka 自我保護模式以及心跳週期長的原因,經常會遇到 Eureka Server 不剔除已關停的節點的問題
    enable-self-preservation: false
    eviction-interval-timer-in-ms: 5000
    waitTimelnMsWhenSyncEmpty: 5 #在伺服器接收請求之前等待的初始時間,在實際生產中應註釋掉此屬性
  • 如果需要將元件註冊進 Eureka 裡,需要把 eureka.client.register-with-eureka 置為 true,或者不管它,使用預設值 true;
  • 只有 Eureka 的客戶端才需要把 eureka.client.register-with-eureka 置為 true;

2.3 在主程式類上標註註解

@EnableEurekaServer:表示該服務為 Eureka 伺服器;


3. 將客戶端註冊進 Eureka 伺服器

3.1 引入 pom.xml 依賴

<!--註冊中心-->
<dependency>  
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
  • 因為每個服務基本上都會註冊進 Eureka 伺服器裡,因此該依賴可以新增到父工程裡,表示公共依賴;

3.2 修改 boostrap.yml 配置檔案

spring:
  application:
    name: xxx-client  #應用程式ID,常寫在 boostrap.yml 下
  profiles:
    active: dev
  cloud:
    config:
      enabled: true
eureka:
  instance:
    preferIpAddress: true  #註冊服務的IP,而不是服務名稱
  client:
    registerWithEureka: true  #向 Eureka 註冊服務
    fetchRegistry: true  #拉取登錄檔的本地副本
    serviceUrl: 
      defaultZone: http://localhost:8761/eureka/  #Eureka 服務模組
  • 每個通過 Eureka 註冊的服務都會有兩個與之相關的 ID:
    • 應用程式 ID:表示一組服務實,D始終是由 spring.application.name 屬性設定的值(寫在 bootstrap.yml 配置檔案中,而不是 application.xml);
    • 例項 ID:一個隨機數,用於代表單個服務例項;
  • 為什麼註冊服務的 IP ,而不是主機名:
    • 在基於伺服器的環境中時:Eureka 在嘗試註冊客戶端服務時,客戶端服務會被分配一個 DNS 支援的主機名,客戶端服務通過這個 DNS 主機名與外界聯絡;
    • 在基於容器的部署(如 Docker)中:容器以隨機生成的主機名啟動,沒有 DNS 記錄;使用主機名將無法解析;

3.3 在主程式類上標註服務發現的註解

  • @EnableEurekaClient:推薦使用 Eureka 作為註冊中心;
  • @EnableDiscoveryClient:推薦使用其他元件作為註冊中心;

4. Eureka Server 的自我保護

4.1 故障現象

  • 如果在Eureka Server的首頁看到以下這段提示,則說明Eureka進入了保護模式:

Eureka 的自我保護

  • Eureka Server 一旦進入自我保護模式,將會嘗試保護其服務登錄檔中的資訊,不再刪除服務登錄檔中的資料,也不會登出任何微服務

4.2 自我保護概述

  • 保護模式主要用於一組客戶端和 Eureka Server 之間存在網路分割槽場景下的保護;
  • 為了防止 Eureka Client 可以正常執行,但是與 Eureka Server 網路不通情況下,Eureka Server 不會立刻將 Eureka Client 服務剔除;

4.3 自我保護原理

  • 預設情況下,如果 Eureka Server 在一定時間內沒有接收到某個微服務例項的心跳,Eureka Server 將會登出該例項(預設90秒);
  • 但是當網路分割槽故障發生(延時、卡頓、擁擠)時,微服務與 Eureka Server 之間無法正常通訊,以上行為可能變得非常危險了;
  • 因為微服務本身其實是健康的,此時本不應該登出這個微服務;
  • Eureka 通過“自我保護模式”來解決這個問題:當 Eureka Server 節點在短時間內丟失過多客戶端時(可能發生了網路分割槽故障),那麼這個節點就會進入自我保護模式;
  • 在自我保護模式中,Eureka Server 會保護服務登錄檔中的資訊,不再登出任何服務例項

自我保護原理

4.4 關閉自我保護機制

  • 使用如下配置可以關閉自我保護機制,保證不可用服務被及時踢除:
  • eureka.server.enable-self-preservation = false


最後

新人制作,如有錯誤,歡迎指出,感激不盡!
歡迎關注公眾號,會分享一些更日常的東西!
如需轉載,請標註出處!
微服務架構 | 3.1 Netflix Eureka 註冊中心

相關文章