在上一文:3W法(what,why,how)入門 Spring Cloud 學(xué)習(xí)后,對 Spring Cloud 有了基本的認(rèn)識,本文主要學(xué)習(xí) Spring Cloud Netflix 之 Eureka,還是老套路---3W法(what,why,how)!
本次學(xué)習(xí)最終實現(xiàn)效果:

版本信息
https://spring.io/projects/spring-cloud
- Spring Boot 版本:2.1.11.RELEASE
- Spring Cloud 版本:Greenwich.SR4
What --- 定義
來自官網(wǎng)的定義:
Eureka is a REST (Representational State Transfer) based service that is primarily used in the AWS cloud for locating services for the purpose of load balancing and failover of middle-tier servers.
Eureka是一種基于REST(具象狀態(tài)傳輸)的服務(wù),主要用于AWS云中定位服務(wù),以實現(xiàn)中間層服務(wù)器的負(fù)載平衡和故障轉(zhuǎn)移。
通俗說:
Eureka 是 Netflix 開源的一款提供服務(wù)注冊和發(fā)現(xiàn)的產(chǎn)品,它提供了完整的 Service Registry 和 Service Discovery 實現(xiàn)。也是 Spring Cloud 體系中最重要最核心的組件之一。
架構(gòu)圖 [來自官網(wǎng)]

上圖描述了 Eureka 的架構(gòu),主要由3個角色組成:
1、Eureka Server
- 提供服務(wù)注冊和發(fā)現(xiàn)
2、Eureka Client (Application Service)
- 服務(wù)提供方
- 將自身服務(wù)注冊到Eureka,從而使服務(wù)消費方能夠找到
3、Eureka Client (Application Client)
- 服務(wù)消費方
- 從Eureka獲取注冊服務(wù)列表,從而能夠消費服務(wù)
WHY --- 特點
What is the need for Eureka?
In AWS cloud, because of its inherent nature, servers come and go. Unlike the traditional load balancers which work with servers with well known IP addresses and host names, in AWS, load balancing requires much more sophistication in registering and de-registering servers with load balancer on the fly. Since AWS does not yet provide a middle tier load balancer, Eureka fills a big gap in the area of mid-tier load balancing.
在AWS云計算中,由于其固有的特性,服務(wù)器來來去去。與使用眾所周知的IP地址和主機(jī)名的服務(wù)器的傳統(tǒng)負(fù)載平衡器不同,在AWS中,負(fù)載平衡器需要更加復(fù)雜地動態(tài)注冊和注銷負(fù)載平衡器服務(wù)器。由于AWS還沒有提供中間層負(fù)載平衡器,Eureka填補(bǔ)了中間層負(fù)載平衡領(lǐng)域的一個巨大空白。
Eureka Server:注冊中心服務(wù)端
注冊中心服務(wù)端主要對外提供了三個功能:
服務(wù)注冊
服務(wù)提供者啟動時,會通過 Eureka Client 向 Eureka Server 注冊信息,Eureka Server 會存儲該服務(wù)的信息,Eureka Server 內(nèi)部有二層緩存機(jī)制來維護(hù)整個注冊表
提供注冊表
服務(wù)消費者在調(diào)用服務(wù)時,如果 Eureka Client 沒有緩存注冊表的話,會從 Eureka Server 獲取最新的注冊表
同步狀態(tài)
Eureka Client 通過注冊、心跳機(jī)制和 Eureka Server 同步當(dāng)前客戶端的狀態(tài)。
Eureka Client:注冊中心客戶端
Eureka Client 是一個 Java 客戶端,用于簡化與 Eureka Server 的交互。Eureka Client 會拉取、更新和緩存 Eureka Server 中的信息。因此當(dāng)所有的 Eureka Server 節(jié)點都宕掉,服務(wù)消費者依然可以使用緩存中的信息找到服務(wù)提供者,但是當(dāng)服務(wù)有更改的時候會出現(xiàn)信息不一致。
Register: 服務(wù)注冊
服務(wù)的提供者,將自身注冊到注冊中心,服務(wù)提供者也是一個 Eureka Client。當(dāng) Eureka Client 向 Eureka Server 注冊時,它提供自身的元數(shù)據(jù),比如 IP 地址、端口,運行狀況指示符 URL,主頁等。
Renew: 服務(wù)續(xù)約
Eureka Client 會每隔 30 秒發(fā)送一次心跳來續(xù)約。 通過續(xù)約來告知 Eureka Server 該 Eureka Client 運行正常,沒有出現(xiàn)問題。 默認(rèn)情況下,如果 Eureka Server 在 90 秒內(nèi)沒有收到 Eureka Client 的續(xù)約,Server 端會將實例從其注冊表中刪除,此時間可配置,一般情況不建議更改。
自我保護(hù)機(jī)制
默認(rèn)情況下,如果 Eureka Server 在一定的 90s 內(nèi)沒有接收到某個微服務(wù)實例的心跳,會注銷該實例。但是在微服務(wù)架構(gòu)下服務(wù)之間通常都是跨進(jìn)程調(diào)用,網(wǎng)絡(luò)通信往往會面臨著各種問題,比如微服務(wù)狀態(tài)正常,網(wǎng)絡(luò)分區(qū)故障,導(dǎo)致此實例被注銷。
Eureka Server 在運行期間會去統(tǒng)計心跳失敗比例在 15 分鐘之內(nèi)是否低于 85%,如果低于 85%,Eureka Server 即會進(jìn)入自我保護(hù)機(jī)制。
Eureka Server 進(jìn)入自我保護(hù)機(jī)制,會出現(xiàn)以下幾種情況:
- Eureka 不再從注冊列表中移除因為長時間沒收到心跳而應(yīng)該過期的服務(wù)
- Eureka 仍然能夠接受新服務(wù)的注冊和查詢請求,但是不會被同步到其它節(jié)點上(即保證當(dāng)前節(jié)點依然可用)
- 當(dāng)網(wǎng)絡(luò)穩(wěn)定時,當(dāng)前實例新的注冊信息會被同步到其它節(jié)點中
Eureka 自我保護(hù)機(jī)制是為了防止誤殺服務(wù)而提供的一個機(jī)制。當(dāng)個別客戶端出現(xiàn)心跳失聯(lián)時,則認(rèn)為是客戶端的問題,剔除掉客戶端;當(dāng) Eureka 捕獲到大量的心跳失敗時,則認(rèn)為可能是網(wǎng)絡(luò)問題,進(jìn)入自我保護(hù)機(jī)制;當(dāng)客戶端心跳恢復(fù)時,Eureka 會自動退出自我保護(hù)機(jī)制。
如果在保護(hù)期內(nèi)剛好這個服務(wù)提供者非正常下線了,此時服務(wù)消費者就會拿到一個無效的服務(wù)實例,即會調(diào)用失敗。對于這個問題需要服務(wù)消費者端要有一些容錯機(jī)制,如重試,斷路器等。
通過在 Eureka Server 配置如下參數(shù),開啟或者關(guān)閉保護(hù)機(jī)制,生產(chǎn)環(huán)境建議打開:
eureka.server.enable-self-preservation=true
HOW --- 使用
Eureka Server
1、pom中添加依賴
參見:pom.xml
2、啟動類
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
3、配置文件
server:
port: 8888
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#eureka.client.registerWithEureka 表示是否將自己注冊到Eureka Server, 默認(rèn)為true。 由于當(dāng)前應(yīng)用就是Eureka Server, 因此設(shè)為 false;
#eureka.client.fetchRegistry 表示是否從Eureka Server獲取注冊信息,默認(rèn)為true。 如果這是一個單點的 Eureka Server,不需要同步其他節(jié)點的數(shù)據(jù),可以設(shè)為false。
Eureka Client
1、pom中添加依賴
參見:pom.xml
2、啟動類
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProviderApplication.class, args);
}
}
3、配置文件
server:
port: 8880
spring:
application:
name: eureka-client-provider
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8888/eureka/
Eureka Server 開啟密碼
1、添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、添加配置信息
spring:
application:
name: eureka-server
security:
user:
name: tyron
password: 123456
3、服務(wù)端開啟basic認(rèn)證
package com.tyron.eureka.server.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
/**
* @Description: security開啟basic認(rèn)證
* @Author: tyron
* @Date: Created in 2019/12/19
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* @Description: 高版本的丟棄了
* security:
* basic:
* enabled: true 配置,應(yīng)該使用以下方式開啟
* @Param: [http]
* @Return: void
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// Configure HttpSecurity as needed (e.g. enable http basic).
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.csrf().disable();
//注意:為了可以使用 http://${user}:${password}@${host}:${port}/eureka/ 這種方式登錄,所以必須是httpBasic,
// 如果是form方式,不能使用url格式登錄
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
4、客戶端注冊地址修改
eureka:
client:
serviceUrl:
defaultZone: http://tyron:123456@localhost:8888/eureka/
#形如:http://${eureka.instance.hostname}:${server.port}/eureka/