1.首先,SpringCloud充分利用了SpringBoot的自動裝配特色
eureka-server的jar包,發如今META-INF下面的配置文件spring.factories,裏面記錄了Spring Boot啓動的時候會加載EurekaServerAutoConfiguration自動配置類
node
2.其次,分析EurekaServerAutoConfiguration類的源碼,咱們發現該類的類頭中存在@ConditionalOnBean的註解,如圖
他表明的意思是,若是想要裝配EurekaServerAutoConfigration,Spring容器中必需要有一個Marker的類的實例。
EurekaServerMarkerConfigration.Marker類:
咱們經過Find Usages功能查詢,在什麼樣的狀況下,咱們會向Spring容器中注入這個Marker對象
咱們發現,若是在Spring Cloud啓動過程當中添加@EnableEurekaServer註解,咱們就會向容器中添加這個Marker的實例對象。也就是說,@EnableEurekaServer註解是Spring Cloud自動加載EurekaServerAutoConfiguration的控制開關。web
3.再次,咱們須要研究加載EurekaServerAutoConfigration類後,會向容器中注入那些Bean,有那些操做
經過structure結構圖,咱們發現,EurekaServer類有一些自動逸的Codec實現,PeerEurekaNodes的回調接口。可是主要的,與EurekaServer啓動相關的Bean有6個:EurekaController、PeerAuareInstanceRegistry、PeerEurekaNodes、EurekaServerContext、EurekaServerBootstrap、FilterRegistationBean。
3.1 EurekaController
注入一個對外的接口——儀表盤/後臺界面,EurekaController。能夠在配置文件中關閉它,可是默認是開啓的狀態。eureka.dashboard.enabled=true算法
3.2 PeerAuareInstanceRegistry 和 PeerEurekaNodes
PeerAwareInstanceRegistry是一個對等節點感知實例註冊器(集羣模式下注冊服務使用到的註冊器)。而且值得注意的是,EurekaServer集羣模式中各個節點是對等的,沒有主從之分。(這一點和Zookeeper不同,zk經過ZAB協議實現了分佈式一致性,可是EurekaServer並無實現任何分佈式算法)
PeerEurekaNodes是用來輔助封裝對等節點相關的信息和操做,好比更新集羣中的對等節點。
這裏咱們稍微看下RefreshablePeerEurekaNodes的源碼,咱們發現它是在繼承PeerEurekaNodes的基礎上實現了ApplicationListener接口,該接口只定義了一個回調方法,處理事件的回調
實際上,實例化RefreshablePeerEurekaNodes對象仍是經過父類的構造方法完成的,這個在代碼的200行中有體現。spring
**3.3 **EurekaServerContext
向容器中注入了EurekaServerContext的對象,具體爲DefaultEurekaServerContext。翻閱DefaultEurekaServerContext源碼中,咱們發現它經過Spring的@PostConstruct註解調用了peerEurekaNodes對象的start()方法
具體在看一下64行調用的peerEurekaNodes.start()方法作了哪些操做
首先,定義了一個線程池Eureka-PeerNodesUpdater——Eureka的更新對等節點線程,最終start方法會開啓這個線程,不停調用93行所指向的updatePeerEurekaNodes()方法。
這個updatePeerEurekaNodes()方法會更新對等節點信息,由於EurekaServer節點可能會不斷的變化(好比,Eureka集羣中某個節點的上下線)
而updatePeerEurekaNodes()方法主要作了什麼呢?
其實就是Removing no longer available peer nodes和Adding new peer nodes。
至此,總結一下,EurekaServerContext的實例化過程,會啓動更新遠程對等節點的線程,不時的刷新遠程對等節點的信息。安全
3.4 EurekaServerBootstrap
注入EurekaServerBootstrap對象,後續的EurekaServer應用的啓動要依靠這個對象併發
3.5 FilterRegistrationBean
在Jersey框架下添加一個攔截器ServletContainer對象,攔截全部的/eureka/的請求,是的Jersey框架開始管理全部的/eureka/的請求框架
4.分析完EurekaServerAutoConfiguration具體注入哪些事情後,咱們在返回EurekaServerAutoConfiguration的類頭分析
它利用的Spring的@Import註解,在EurekaServerAutoConfigration注入完全部的Bean後,再次調用了EurekaServerInitializerConfigration對象,裝配了它。
因爲EurekaServerInitializerConfiguration實現了SmartLifecycle接口,全部Spring容器的Bean建立完成後會回調start()方法。(順便說一下,EurekaServerInitializerConfiguration類沒有顯式的無參方法,因此它的初始化會調用默認的無參構造方法,且幾乎不會作什麼操做)
而start()方法會開啓一個後臺線程去使用eurekaServerBootstrap對象初始化Context。分佈式
4.1 分析eurekaServerBootstrap對象的contextInitialized()方法(在3.4步驟時實例化的)
初始化上下文實際上就是初始化環境變量方法的調用和初始化EurekaServerContext()方法。其中initEurekaEnvironment()方法就是讀取配置,若是沒有配置則設置成默認配置
再看看initEurekaServerContext()方法
這個方法中大致分爲5步,1.註冊序列化的轉化器;2.對aws的狀況進行特殊處理;3.爲非IOC容器提供獲取serverContext對象接口;4.從其餘註冊中心複製註冊新信息;5.改變EurekaServer的狀態,EurekaServer啓動完成的標誌
這裏值得關注的是步驟4,如何複製其餘節點的註冊信息到本EurekaServer上。post
4.2 registry.syncUp()方法
這裏224行的register()方法是作把遠程得到過來的註冊信息註冊到本身的註冊表中(map中)
register()方法中具體就是在保證線程安全的狀況下對registry對象進行操做
綜上所述,registry.syncUp()方法就是拷貝其餘對等節點的註冊信息到本身的註冊表map中.net
4.3 registry.openForTraffic()方法
這裏,咱們確定選擇Peer的實現,由於Eureka Server的啓動通常都是集羣模式
openForTraffic()方法裏,具體就是設置實例狀態爲UP,並調用父類的postInit()方法
在com.netflix.eureka.registry.AbstractInstanceRegistry#postInit()方法中,主要是啓動失效剔除定時任務的,具體的任務邏輯在EvicationTask中定義。
這裏調用了 AbstractInstanceRegistry的evict()方法
這個方法就是根據失效時常剔除失效的服務
綜上所屬,registry.syncUp()就是開啓一個服務失效剔除線程
因此,
Eureka Server啓動過程就是在@EnableEurekaServer開關的基礎上,建立了一些後臺進程去同步註冊信息,併發佈一個Jersey的web服務。它充分利用了Spring Boot的自動裝配功能和spring的一些回調接口實現。