1. 程式人生 > >微服務之服務中心—Eureka

微服務之服務中心—Eureka

Eureka 簡介
Eureka 是 Spring Cloud Netflix 的一個子模組,也是核心模組之一,用於雲端服務發現,是一
基於 REST 的服務,用於定位服務,以實現雲端中間層服務發現和故障轉移。

為什麼要用 Eureka
在傳統架構中,當呼叫 API 或者發起網路通訊的時候,我們需要知道被呼叫方的 IP、埠
號,大部分情況是通過域名和服務埠,事實上基於 DNS 的服務發現,而這種 DNS 方式,通
常都是通過 nginx 或者其他代理軟體實現的,因為物理機器的 ip 和埠號通常都是固定的,
所以 nginx 中的配置資訊也是固定的,服務列表需要通過手動去重新整理,隨著後臺複雜度的增
加,後臺服務也越來越多,手動重新整理的方式效率低而且容易出錯,當後臺發生故障時,處理
也會變得很麻煩。
在微服務架構中,尤其是使用了 Docker 等虛擬化技術的微服務,其 IP 和 port 都是動態分配
的,服務例項數也是動態變化的,那麼就需要精細而準確的服務發現機制。當你有一個新的
服務執行後,服務中心可以感知到,然後把它加新增到服務列表裡,然後當它死掉後,會從
服務中心移除,而作為一個服務,對其它服務公開的只是服務名稱,而不是最終的服務地址
URL,這對於雲平臺容器化架構來說是非常重要的。

Eureka 原理

 

一個服務例項被啟動時,它的網路地址會被寫到登錄檔上;當服務例項終止時,再從登錄檔
中刪除。這個服務例項的登錄檔通過心跳機制動態重新整理。
Netflix OSS 提供了一個客戶端服務發現的好例子。Netflix Eureka 是一個服務登錄檔,提供了
REST API 用來管理服務例項的註冊和查詢可用的例項。Netflix Ribbon 是一個 IPC 客戶端,和
Eureka 一起處理可用服務例項的負載均衡。

Eureka 架構

 

• Eureka Server: 註冊中心
  服務都註冊在哪裡,哪裡就可稱為 Eureka Server
• Eureka Client
  註冊在註冊中心可以是服務的提供者(Applicaton Service)或者服務的消費者
     (Application Client),這兩類都被稱為 Eureka client
• Application Service:服務提供者
• Application Client:服務消費者
• Register:服務註冊
  當 Eureka 客戶端向 Eureka Server 註冊時,會向 Eurekaserver 註冊自己的資訊(比如 IP,
  埠,微服務名等),Eureka Server 會儲存這些資訊。
• Renew:服務續約
  微服務啟動後,會週期性(預設 30 秒)地向 Eureka Server 傳送心跳。如果 Eureka Server
  在一定時間內沒有接收到某個微服務例項的心跳,Eureka Server 將會登出該例項(預設 90
  秒)
• Cancel:服務下線
  Eureka Client 在程式關閉時向 Eureka Server 傳送取消請求。 傳送請求後,該客戶端例項
  資訊將從伺服器的例項登錄檔中刪除。該下線請求不會自動完成,它需要呼叫以下內容:
  DiscoveryManager.getInstance().shutdownComponent()

Eureka 特點

  1. Eureka Client 會快取服務登錄檔中的資訊,並將其快取在本地,該註冊列表資訊定期
(預設 30 秒)更新一次,因此微服務無須每次請求都查詢 Eureka Server,從而降低了 Eureka
Server 的壓力;其次,當註冊中心掛了,客戶端之間依然可以通過快取中的資訊進行呼叫;
註冊中心重啟後,客戶端會繼續註冊進來。
  2.當服務提供者掛了,在關閉自我保護的情況下,註冊中心在規定時間(預設是 60s)內
移除客戶端。
  3.自我保護,當一個新的 Eureka Server 出現時,它嘗試從相鄰節點獲取所有例項登錄檔信
息。如果從 Peer 節點獲取資訊時出現問題,Eureka Serve 會嘗試其他的 Peer 節點。如果服務
器能夠成功獲取所有例項,則根據該資訊設定應該接收的更新閾值。如果有任何時間,
Eureka Serve 接收到的續約低於為該值配置的百分比(預設為 15 分鐘內低於 85%),則服務
器開啟自我保護模式,即不再剔除註冊列表的資訊。  

 

 

Eureka 實踐作業

服務註冊中心

1. 在 IDEA 中建立一個 Spring Cloud 工程,引入 Eureka-Server 包,pom 檔案整體如下:

  

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo</name>
<description>Demo project for Spring Boot</description>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

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


<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>


</project>

2. application.yml 配置
# 單例模式啟動 Eureka Server
server:
port: 8761 # 啟動埠
eureka:
client:
registerWithEureka: false #false: 不作為一個客戶端註冊到註冊中心
fetchRegistry: false # 此客戶端是否獲取 eureka 伺服器登錄檔上的註冊資訊
serviceUrl:
defaultZone: http://localhost:8761/eureka

  配置解釋:
  • registerWithEureka:表示是否將自己註冊到 Eureka Server,預設為 true。由於當前應用
    就是 Eureka Server,故而設定為 false。
  • fetchRegistry:表示是否從 Eureka Server 獲取註冊資訊,預設為 true。因為這是一個單
         點的 Eureka Server,不需要同步其他的 Eureka Server 節點的資料,故而設定為 false。
  • defalseZone:設定與 Eureka Server 互動的地址,查詢服務和註冊服務都需要依賴這個地
         址。

3. 編寫啟動類,在啟動類上新增@EnableEurekaServer 註解,宣告這是一個 Eureka Server。

package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class DemoApplication {

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

4. 訪問 http://localhost:8761/,如下圖所示:





將微服務註冊到 Eureka Server 上
1. 在 IDEA 中建立一個 Spring Cloud 工程,pom 檔案整體如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.eureka</groupId>
<artifactId>applicaton-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>service</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Camden.SR7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

2. application.yml 配置
# HTTP (Tomcat) port
server:
port: 8082
spring:
application:
name: micro-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/

3. 編寫啟動類,在啟動類上新增@SpringBootApplication @EnableDiscoveryClient 註解,宣告這
是一個 Eureka Client。

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;


@SpringBootApplication
@EnableDiscoveryClient
public class EurekaServerApplication {

public static void main(String[] args) {

SpringApplication.run(EurekaServerApplication.class, args);
}
}

4. 啟動後,重新訪問 http://localhost:8761/(不要關閉上一個啟動的服務),如下圖所示,我們可以看到剛剛啟動的服務已經
註冊到我們的服務註冊中心中。

 

注:如出現一行紅色大字(比如再次啟動服務時的情況下)  如下圖


這是一種自我保護機制。Eureka Server在執行期間,會統計心跳失敗的比例在15分鐘之內是否低於85%,如果出現低於的情況(在單機除錯的時候很容易滿足,實際在生產環境上通常是由於網路不穩定導致),Eureka Server會將當前的例項註冊資訊保護起來,同時提示這個警告。