Eureka注冊中心原理

image

前言

哈嘍大家好,本人最近面試經(jīng)歷有點坎坷,很久沒更新了。但我打開公眾號發(fā)現(xiàn)粉絲居然還漲了,非常感謝各位一直以來的關(guān)注,接下來會整理一下最近面試遇到知識點分享給大家。

Eureka 是什么

Eureka是Netflix開發(fā)的服務(wù)發(fā)現(xiàn)框架,本身是一個基于REST的服務(wù),主要用于定位運行在AWS域中的中間層服務(wù),以達(dá)到負(fù)載均衡和中間層服務(wù)故障轉(zhuǎn)移的目的。SpringCloud將它集成在其子項目spring-cloud-netflix中,以實現(xiàn)SpringCloud的服務(wù)發(fā)現(xiàn)功能。

架構(gòu)原理

image
  • Register(服務(wù)注冊):把自己的IP和端口注冊給Eureka。
  • Renew(服務(wù)續(xù)約):發(fā)送心跳包,每30秒發(fā)送一次。告訴Eureka自己還活著。
  • Cancel(服務(wù)下線):當(dāng)provider關(guān)閉時會向Eureka發(fā)送消息,把自己從服務(wù)列表中刪除。防止consumer調(diào)用到不存在的服務(wù)。
  • Get Registry(獲取服務(wù)注冊列表):獲取其他服務(wù)列表。
  • Replicate(集群中數(shù)據(jù)同步):eureka集群中的數(shù)據(jù)復(fù)制與同步。
  • Make Remote Call(遠(yuǎn)程調(diào)用):完成服務(wù)的遠(yuǎn)程調(diào)用。

Eureka包含兩個組件:Eureka Server和Eureka Client。

Eureka Server

Eureka Server提供服務(wù)注冊服務(wù),各個節(jié)點啟動后,會在Eureka Server中進(jìn)行注冊,這樣Eureka Server中的服務(wù)注冊表中將會存儲所有可用服務(wù)節(jié)點的信息,服務(wù)節(jié)點的信息可以在界面中直觀的看到。

Eureka Server本身也是一個服務(wù),默認(rèn)情況下會自動注冊到Eureka注冊中心。

Eureka Server注冊中心集群中每個節(jié)點都是平等的,集群中的所有節(jié)點同時對外提供服務(wù)的發(fā)現(xiàn)和注冊等功能。同時集群中每個Eureka Server節(jié)點又是一個微服務(wù),也就是說,每個節(jié)點都可以在集群中的其他節(jié)點上注冊當(dāng)前服務(wù)。又因為每個節(jié)點都是注冊中心,所以節(jié)點之間又可以相互注冊當(dāng)前節(jié)點中已注冊的服務(wù),并發(fā)現(xiàn)其他節(jié)點中已注冊的服務(wù)。

如果搭建單機版的Eureka Server注冊中心,則需要配置取消Eureka Server的自動注冊邏輯。畢竟當(dāng)前服務(wù)注冊到當(dāng)前服務(wù)代表的注冊中心中是一個說不通的邏輯。

Eureka Server通過Register、Get、Renew等接口提供服務(wù)的注冊、發(fā)現(xiàn)和心跳檢測等服務(wù)。

Eureka Server為了避免同時讀寫內(nèi)存數(shù)據(jù)結(jié)構(gòu)造成的并發(fā)沖突問題,還采用了多級緩存機制來進(jìn)一步提升服務(wù)請求的響應(yīng)速度。

image

1、在拉取注冊表的時候:

首先從ReadOnlyCacheMap里查緩存的注冊表。
若沒有,就找ReadWriteCacheMap里緩存的注冊表。
如果還沒有,就從內(nèi)存中獲取實際的注冊表數(shù)據(jù)。

2、在注冊表發(fā)生變更的時候:

會在內(nèi)存中更新變更的注冊表數(shù)據(jù),同時過期掉ReadWriteCacheMap。
此過程不會影響ReadOnlyCacheMap提供人家查詢注冊表。

一段時間內(nèi)(默認(rèn)30秒),各服務(wù)拉取注冊表會直接讀ReadOnlyCacheMap
30秒過后,Eureka Server的后臺線程發(fā)現(xiàn)ReadWriteCacheMap已經(jīng)清空了,也會清空ReadOnlyCacheMap中的緩存
下次有服務(wù)拉取注冊表,又會從內(nèi)存中獲取最新的數(shù)據(jù)了,同時填充各個緩存。

多級緩存機制的優(yōu)點是什么?

盡可能保證了內(nèi)存注冊表數(shù)據(jù)不會出現(xiàn)頻繁的讀寫沖突問題。
并且進(jìn)一步保證對Eureka Server的大量請求,都是快速從純內(nèi)存走,性能極高。

Eureka Client

Eureka Client是一個java客戶端,用于簡化與Eureka Server的交互,客戶端同時也具備一個內(nèi)置的、使用輪詢(round-robin)負(fù)載算法的負(fù)載均衡器。

在應(yīng)用啟動后,將會向Eureka Server發(fā)送心跳,默認(rèn)周期為30秒,如果Eureka Server在多個心跳周期內(nèi)沒有接收到某個節(jié)點的心跳,Eureka Server將會從服務(wù)注冊表中把這個服務(wù)節(jié)點移除(默認(rèn)90秒)。

Eureka Client分為兩個角色,分別是:Application Service(Service Provider)和Application Client(Service Consumer)

通過定時任務(wù)30秒拉取一次注冊表,30秒發(fā)起一次心跳

單機版

注冊中心依賴

pom.xml

<!-- spring cloud Eureka Server 啟動器 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

注冊中心啟動類

EurekaServerApplication.java

@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {

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

注冊中心配置

application.yml

server:  # 服務(wù)端口
  port: 9090  
spring:
  application:  # 應(yīng)用名字,eureka 會根據(jù)它作為服務(wù)id
    name: spring-cloud-eureka-server    
eureka:
  instance:
    hostname: localhost
  client:
    service-url:   #  eureka server 的地址, 咱們單實例模式就寫自己好了
      defaultZone:  http://localhost:9090/eureka
    register-with-eureka: false  # 不向eureka server 注冊自己
    fetch-registry: false  # 不向eureka server 獲取服務(wù)列表

服務(wù)提供者依賴

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

服務(wù)提供者依賴

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

服務(wù)提供者配置

application.yml

server:
  port: 7070
spring:
  application:
    name: spring-cloud-order-service-provider
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:9090/eureka
    fetch-registry: true
    register-with-eureka: true

服務(wù)提供者與服務(wù)消費者配置依賴類似,只是消費者需要restemplate進(jìn)行消費,而服務(wù)提供者需要暴露Controller接口給消費者調(diào)用。

集群版

1、修改host文件

127.0.0.1 EurekaServerA
127.0.0.1 EurekaServerB

2、修改application.yml

這里是2個Eureka Server組成的集群,然后u1 的往u2 上面注冊,u2往u1上面注冊

spring:
  application:
    name: spring-cloud-eureka-server


---
spring:
  profiles: u1
eureka:
  instance:
    hostname: EurekaServerA
  client:
    service-url:
      defaultZone:  http://EurekaServerB:9091/eureka
    register-with-eureka: true
    fetch-registry: true
server:
  port: 9090
---
spring:
  profiles: u2
eureka:
  instance:
    hostname: EurekaServerB
  client:
    service-url:
      defaultZone:  http://EurekaServerA:9090/eureka
    register-with-eureka: true
    fetch-registry: true
server:
  port: 9091

3、修改服務(wù)提供者或消費者application.yml

server:
  port: 7070
spring:
  application:
    name: spring-cloud-order-service-provider
eureka:
  client:
    service-url:
      defaultZone: http://EurekaServerA:9090/eureka,http://EurekaServerB:9091/eureka
    fetch-registry: true
    register-with-eureka: true
  instance:
    prefer-ip-address: true   # 使用ip注冊
    #自定義實例顯示格式,添加版本號
    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@

服務(wù)保護(hù)

服務(wù)保護(hù)模式(自我保護(hù)模式)

一般情況下,微服務(wù)在Eureka上注冊后,會每30秒發(fā)送心跳包,Eureka通過心跳來判斷服務(wù)時候健康,同時會定期刪除超過90秒沒有發(fā)送心跳服務(wù)。

導(dǎo)致Eureka Server接收不到心跳包的可能:一是微服務(wù)自身的原因,二是微服務(wù)與Eureka之間的網(wǎng)絡(luò)故障。通常微服務(wù)的自身的故障只會導(dǎo)致個別服務(wù)出現(xiàn)故障,一般不會出現(xiàn)大面積故障,而網(wǎng)絡(luò)故障通常會導(dǎo)致Eureka Server在短時間內(nèi)無法收到大批心跳。慮到這個區(qū)別,Eureka設(shè)置了一個閥值,當(dāng)判斷掛掉的服務(wù)的數(shù)量超過閥值時,Eureka Server認(rèn)為很大程度上出現(xiàn)了網(wǎng)絡(luò)故障,將不再刪除心跳過期的服務(wù)。

那么這個閥值是多少呢?Eureka Server在運行期間,會統(tǒng)計心跳失敗的比例在15分鐘內(nèi)是否低于85%,如果低于85%,Eureka Server則任務(wù)是網(wǎng)絡(luò)故障,不會刪除心跳過期服務(wù)。

這種服務(wù)保護(hù)算法叫做Eureka Server的服務(wù)保護(hù)模式。

這種不刪除的,90秒沒有心跳的服務(wù),稱為無效服務(wù),但是還是保存在服務(wù)列表中。如果Consumer到注冊中心發(fā)現(xiàn)服務(wù),則Eureka Server會將所有好的數(shù)據(jù)(有效服務(wù)數(shù)據(jù))和壞的數(shù)據(jù)(無效服務(wù)數(shù)據(jù))都返回給Consumer。

關(guān)閉服務(wù)保護(hù)模式

# 關(guān)閉自我保護(hù):true為開啟自我保護(hù),false為關(guān)閉自我保護(hù)
eureka.server.enableSelfPreservation=false
# 清理間隔(單位:毫秒,默認(rèn)是60*1000),當(dāng)服務(wù)心跳失效后多久,刪除服務(wù)。
eureka.server.eviction.interval-timer-in-ms=60000

優(yōu)雅關(guān)閉服務(wù)

在Spring Cloud中,可以通過HTTP請求的方式,通知Eureka Client優(yōu)雅停服,這個請求一旦發(fā)送到Eureka Client,那么Eureka Client會發(fā)送一個shutdown請求到Eureka Server,Eureka Server接收到這個shutdown請求后,會在服務(wù)列表中標(biāo)記這個服務(wù)的狀態(tài)為down,同時Eureka Client應(yīng)用自動關(guān)閉。這個過程就是優(yōu)雅停服。

如果使用了優(yōu)雅停服,則不需要再關(guān)閉Eureka Server的服務(wù)保護(hù)模式。

1、POM依賴:

優(yōu)雅停服是通過Eureka Client發(fā)起的,所以需要在Eureka Client中增加新的依賴,這個依賴是autuator組件,添加下述依賴即可。

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

2、修改全局配置文件:

Eureka Client默認(rèn)不開啟優(yōu)雅停服功能,需要在全局配置文件中新增如下內(nèi)容:

# 啟用shutdown,優(yōu)雅停服功能
endpoints.shutdown.enabled=true
# 禁用密碼驗證
endpoints.shutdown.sensitive=false

3、發(fā)起shutdown請求:

必須通過POST請求向Eureka Client發(fā)起一個shutdown請求。請求路徑為:http://ip:port/shutdown。可以通過任意技術(shù)實現(xiàn),如:HTTPClient、form表單,AJAX等。

建議使用優(yōu)雅停服方式來關(guān)閉Application Service/Application Client服務(wù)。

源碼剖析

Eureka Server

image

Eureka Client

image

思考

文章到此結(jié)束,那么以下問題是否有答案了呢?

  • 1、為什么要用注冊中心,用Nginx不行?
  • 2、Eureka的client和server是如何工作的,服務(wù)注冊,服務(wù)發(fā)現(xiàn)是怎么做到的?
  • 3、Eureka集群是如何工作的,一致性能夠保證?

參考文章

https://blog.csdn.net/zhuyanlin09/article/details/89598245

https://github.com/Netflix/eureka/wiki

http://www.lxweimin.com/p/56155d2bde6b

https://cloud.tencent.com/developer/article/1033336

https://www.cnblogs.com/jing99/p/11576133.html

https://www.cnblogs.com/liconglong/p/13223182.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,606評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,582評論 3 418
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,540評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,028評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 71,801評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,223評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,294評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,442評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,976評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,800評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,996評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,543評論 5 360
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,233評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,662評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,926評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,702評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 47,991評論 2 374

推薦閱讀更多精彩內(nèi)容