Eureka服務端源碼流程梳理

1、簡述spring

spring cloud三步走,一導包,二依賴,三配置爲咱們簡化了太多東西,以致於不少東西知其然不知其因此然,瞭解底層實現以後對於一些問題咱們也能夠快速的定位問題所在。緩存

spring cloud不少東西都是基於註解實現的,最開始接觸的很迷,怎麼一個註解就能夠搞定這麼多事情,那些配置是怎麼加載到spring容器的?springboot

瞭解springboot的都會知道在jar包裏面通常都會都有一個spring.factories的配置文件,裏面配置了不少配置類得路徑,這裏就是加載相關配置類得入口。網絡

其次就是針對springcloud裏面註解,通常來講在某個註解同級目錄裏面都會有xxxxxxxAutoConfiguration這樣的配置類,裏面會去初始化相關的bean,好比在EnableEurekaServer註解的同級目錄就有EurekaServerAutoConfiguration這個玩意兒,而EurekaServerAutoConfiguration這個玩意兒就是配置在spring.factories裏面的架構

2、、Eureka架構圖及描述app

 

 

 

1.服務註冊(register):Eureka Client會經過發送REST請求的方式向Eureka Server註冊本身的服務,提供自身的元數據,好比ip地址、端口、運行情況指標的url、主頁地址等信息。Eureka Server接收到註冊請求後,就會把這些元數據信息存儲在一個雙層的Map中。
2.服務續約(renew):在服務註冊後,Eureka Client會維護一個心跳來持續通知Eureka Server,說明服務一直處於可用狀態,防止被剔除。Eureka Client在默認的狀況下會每隔30秒(eureka.instance.leaseRenewallIntervalInSeconds)發送一次心跳來進行服務續約。
3.服務同步(replicate):Eureka Server之間會互相進行註冊,構建Eureka Server集羣,不一樣Eureka Server之間會進行服務同步,用來保證服務信息的一致性。
4.獲取服務(get registry):服務消費者(Eureka Client)在啓動的時候,會發送一個REST請求給Eureka Server,獲取上面註冊的服務清單,而且緩存在Eureka Client本地,默認緩存30秒(eureka.client.registryFetchIntervalSeconds)。同時,爲了性能慮,Eureka Server也會維護一份只讀的服務清單緩存,該緩存每隔30秒更新一次。
5.服務調用:服務消費者在獲取到服務清單後,就能夠根據清單中的服務列表信息,查找到其餘服務的地址,從而進行遠程調用。Eureka有Region和Zone的概念,一個Region能夠包含多個Zone,在進行服務調用時,優先訪問處於同一個Zone中的服務提供者。
6.服務下線(cancel):當Eureka Client須要關閉或重啓時,就不但願在這個時間段內再有請求進來,因此,就須要提早先發送REST請求給Eureka Server,告訴Eureka Server本身要下線了,Eureka Server在收到請求後,就會把該服務狀態置爲下線(DOWN),並把該下線事件傳播出去。
7.服務剔除(evict):有時候,服務實例可能會由於網絡故障等緣由致使不能提供服務,而此時該實例也沒有發送請求給Eureka Server來進行服務下線,因此,還須要有服務剔除的機制。Eureka Server在啓動的時候會建立一個定時任務,每隔一段時間(默認60秒),從當前服務清單中把超時沒有續約(默認90秒,eureka.instance.leaseExpirationDurationInSeconds)的服務剔除。
8.自我保護:既然Eureka Server會定時剔除超時沒有續約的服務,那就有可能出現一種場景,網絡一段時間內發生了異常,全部的服務都沒可以進行續約,Eureka Server就把全部的服務都剔除了,這樣顯然不太合理。因此,就有了自我保護機制,當短期內,統計續約失敗的比例,若是達到必定閾值,則會觸發自我保護的機制,在該機制下,Eureka Server不會剔除任何的微服務,等到正常後,再退出自我保護機制。自我保護開關(eureka.server.enable-self-preservation: false)ide

3、EurekaServer源碼流程梳理圖微服務

首先推薦一個在線畫圖工具https://www.processon.com,按照流程圖裏面的類和方法去和源碼對號入座。
工具

 

 

4、服務端註冊接口和註冊列表獲取接口(2019.05.03補充)
性能

多級緩存設計思想:儘量保證了內存註冊表數據不會出現頻繁的讀寫衝突問題,進一步保證對Eureka Server的大量請求,都是快速從純內存走,性能極高

1.在拉取註冊表的時候:
    首先從ReadOnlyCacheMap裏查緩存的註冊表。
    若沒有,就找ReadWriteCacheMap裏緩存的註冊表。
    若是尚未,就從內存中獲取實際的註冊表數據。
2.在註冊表發生變動的時候:
    會在內存中更新變動的註冊表數據,同時過時掉ReadWriteCacheMap。
    此過程不會影響ReadOnlyCacheMap提供人家查詢註冊表。
    默認每30秒Eureka Server會將ReadWriteCacheMap更新到
    ReadOnlyCacheMap裏
    默認每180秒Eureka Server會將ReadWriteCacheMap裏是數據失效
   下次有服務拉取註冊表,又會從內存中獲取最新的數據了,同時填充 各級緩存。

 

存在的問題:

1.當咱們eureka服務實例有註冊或下線或有實例發生故障,內存註冊表雖然會及時更新數據,可是客戶端不必定能及時感知到,可能會過30秒才能感知到,由於客戶端拉取註冊表實例這裏面有一個多級緩存機制


2.服務剔除的不是默認90秒沒心跳的實例,剔除的是180秒沒心跳的實例(eureka的bug致使)

 

/**
     * Renew the lease, use renewal duration if it was specified by the
     * associated {@link T} during registration, otherwise default duration is
     * {@link #DEFAULT_DURATION_IN_SECS}.
     */
    public void renew() {
        lastUpdateTimestamp = System.currentTimeMillis() + duration;

    }

 

加了兩次duration值,com.netflix.eureka.lease.Lease#isExpired(long)

 

 

 /**
     * Checks if the lease of a given {@link com.netflix.appinfo.InstanceInfo} has expired or not.
     *
     * Note that due to renew() doing the 'wrong" thing and setting lastUpdateTimestamp to +duration more than
     * what it should be, the expiry will actually be 2 * duration. This is a minor bug and should only affect
     * instances that ungracefully shutdown. Due to possible wide ranging impact to existing usage, this will
     * not be fixed.
     *
     * @param additionalLeaseMs any additional lease time to add to the lease evaluation in ms.
     */
    public boolean isExpired(long additionalLeaseMs) {
        return (evictionTimestamp > 0 || System.currentTimeMillis() > (lastUpdateTimestamp + duration + additionalLeaseMs));
    }

 

 

 

流程圖:

相關文章
相關標籤/搜索