摘要: 原創出處 http://www.iocoder.cn/Eureka/transport/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
本文主要基於 Eureka 1.8.X 版本
- 1. 概述
- 2. EurekaHttpClient
- 3. EurekaHttpClient
- 4. AbstractJerseyEurekaHttpClient
- 5. EurekaHttpClientDecorator
- 5.1 MetricsCollectingEurekaHttpClient
- 5.2 RedirectingEurekaHttpClient
- 5.3 RetryableEurekaHttpClient
- 5.4 SessionedEurekaHttpClient
- 6. 創建網絡通訊客戶端
- Eureka-Client 請求 Eureka-Server 的網絡通信
- Eureka-Server 集羣內,Eureka-Server 請求 其它的Eureka-Server 的網絡通信
- 粉色部分 —— EurekaJerseyClient ,對基於 Jersey Server 的 Eureka-Server 的 Jersey 客戶端封裝。
- 綠色部分 —— EurekaHttpClient ,Eureka-Server HTTP 訪問客戶端,定義了具體的 Eureka-Server API 調用方法。如果把 DiscoveryClient 類比成 Service ,那麼 EurekaHttpClient 可以類比城 Dao 。
- 綜色部分 —— EurekaHttpClient 實現類,真正實現了具體的 Eureka-Server API 調用方法。
- 紅色部分 —— EurekaHttpClient 委託類,提供了會話、重試、重定向、監控指標收集等特性。
- 黃色部分 —— EurekaHttpClientFactory,用於創建 EurekaHttpClient 。
- 請支持正版。下載盜版,等於主動編寫低級 BUG 。
- 程序猿DD —— 《Spring Cloud微服務實戰》
- 周立 —— 《Spring Cloud與Docker微服務架構實戰》
- 兩書齊買,京東包郵。
com.sun.jersey.client.apache4.ApacheHttpClient4
,基於 Apache HttpClient4 實現的 Jersey Client 。com.netflix.discovery.shared.transport.jersey.ApacheHttpClientConnectionCleaner
,Apache HttpClient 空閒連接清理器,負責週期性關閉處於half-close
狀態的空閒連接。點擊 鏈接 查看帶中文註釋的 ApacheHttpClientConnectionCleaner。推薦閱讀:《HttpClient容易忽視的細節——連接關閉》 。- MyDefaultApacheHttpClient4Config ,繼承自
com.sun.jersey.client.apache4.config.DefaultApacheHttpClient4Config
,實現自定義配置。點擊 鏈接 查看帶中文註釋的 MyDefaultApacheHttpClient4Config。例如 :- 自定義的請求、響應的編解碼器
com.netflix.discovery.provider.DiscoveryJerseyProvider
。 - 禁用重定向,使用 RedirectingEurekaHttpClient 實現該特性。
- 自定義 UserAgent 。
- 自定義 Http Proxy 。
- SSL 功能的增強。ApacheHttpClient4 使用的是 Apache HttpClient 4.1.1 版本,
com.netflix.discovery.shared.transport.jersey.SSLSocketFactoryAdapter
將 Apache HttpClient 4.3.4 對 SSL 功能的增強適配到老版本 API 。點擊 鏈接 查看帶中文註釋的 SSLSocketFactoryAdapter。
- 自定義的請求、響應的編解碼器
jerseyClient
屬性,Jersey Client ,使用上文的EurekaHttpClient#getClient(...)
方法,獲取 ApacheHttpClient4 。serviceUrl
屬性,請求的 Eureka-Server 地址。#register()
方法,實現向 Eureka-Server 註冊應用實例。其他方法代碼類似。- 第 22 至 26 行 :設置請求地址。
第 28 行 :調用
#addExtraHeaders(...)
方法,設置請求頭( header )。該方法是抽象方法,提供子類實現自定義的請求頭。代碼如下:protected abstract void addExtraHeaders(Builder webResource);- x
- 第 29 至 34 行 :請求 Eureka-Server 。
- 第 35 至 36 行 :解析響應結果,創建 EurekaHttpResponse 。
- x
實現
AbstractJerseyEurekaHttpClient#addExtraHeaders()
方法,添加自定義頭x-netflix-discovery-replication=true
,代碼如下:protected void addExtraHeaders(Builder webResource) {webResource.header(PeerEurekaNode.HEADER_REPLICATION, "true");}重寫了
#sendHeartBeat(...)
方法,在 《Eureka 源碼解析 —— Eureka-Server 集羣同步》 有詳細解析。- 實現
com.netflix.eureka.cluster.HttpReplicationClient
接口,實現了#submitBatchUpdates(...)
方法,在 《Eureka 源碼解析 —— Eureka-Server 集羣同步》 有詳細解析。 #execute(...)
抽象方法,子類實現該方法,實現自己的特性。#register()
方法,實現向 Eureka-Server 註冊應用實例。其他方法代碼類似。- 調用
#execute(...)
方法,並將原有的註冊實現通過 RequestExecutor 傳遞進去。 - 子類在實現的
#execute(...)
方法,可以調用RequestExecutor#execute(...)
方法,繼續執行原有邏輯。 - 參考設計模式:《設計模式 ( 十九 ) 模板方法模式Template method(類行爲型)》 。
- 調用
RequestType ,請求類型枚舉類。代碼如下:
// EurekaHttpClientDecorator.javapublic enum RequestType {Register,Cancel,SendHeartBeat,StatusUpdate,DeleteStatusOverride,GetApplications,GetDelta,GetVip,GetSecureVip,GetApplication,GetInstance,GetApplicationInstance}
RequestExecutor ,請求執行器接口。接口代碼如下:
// EurekaHttpClientDecorator.javapublic interface RequestExecutor<R> {/* 執行請求@param delegate 委託的 EurekaHttpClient* @return 響應/EurekaHttpResponse<R> execute(EurekaHttpClient delegate);/@return 請求類型*/RequestType getRequestType();}
- 請注意,每個委託着實現類,上面可能有類型爲 EurekaHttpClientFactory 的屬性,用於創建其委託的 EurekaHttpClient 。爲什麼會有 Factory ?例如,RetryableEurekaHttpClient 重試請求多個 Eureka-Server 地址時,每個 Eureka-Server 地址會創建一個 EurekaHttpClient 。所以,下文涉及到 EurekaHttpClientFactory 和委託的 EurekaHttpClient 的地方,你都需要仔細理解。
- 第 10 行 :調用
RequestExecutor#execute(...)
方法,繼續執行請求。delegate
屬性,對應 JerseyApplicationClient 。
- 注意:和我們理解的常規的 302 狀態返回處理不同!!!
- 整個分成兩部分:【第 4 至 15 行】、【第 16 至 24 行】。
- 前者,意味着未找到非返回 302 狀態碼的 Eureka-Server ,此時通過在原始傳遞進來的
serviceUrls
執行請求,尋找非 302 狀態碼返回的 Eureka-Server。- 當返回非 302 狀態碼時,找到非返回 302 狀態碼的 Eureka-Server 。
- 當返回 302 狀態碼時,向新的重定向的 Eureka-Server 執行請求直到成功找到或超過最大次數。
- 後者,意味着當前已經找到非返回 302 狀態碼的 Eureka-Server ,直接執行請求。注意 :此時 Eureka-Server 再返回 302 狀態碼,不再處理。
- 目前 Eureka 1.x 的 Eureka-Server 不存在返回 302 狀態碼,猜測和 Eureka 2.X TODO[0028]:寫入集羣和讀取集羣 有關。
- 前者,意味着未找到非返回 302 狀態碼的 Eureka-Server ,此時通過在原始傳遞進來的
- 【前者】第 5 行 :使用初始的
serviceEndpoint
( 相當於serviceUrls
) 創建委託 EurekaHttpClient 。 - 【前者】第 7 行 :調用
#executeOnNewServer(...)
方法,通過執行請求的方式,尋找非 302 狀態碼返回的 Eureka-Server。實現代碼,點擊 鏈接 查看帶中文註釋的代碼實現。 - 【前者】【前者】第 9 行 :關閉原有的
delegateRef
( 因爲此處可能存在併發,多個線程都找到非 302 狀態碼返回的 Eureka-Server ),並設置當前成功非 302 請求的 EurekaHttpClient 到delegateRef
。 - 【前者】第 13 行 :關閉
currentEurekaClientRef
,當請求發生異常或者超過最大重定向次數。 - 【後者】第 18 行 :意味着當前已經找到非返回 302 狀態碼的 Eureka-Server ,直接執行請求。
- 【後者】第 21 至 22 行 :執行請求發生異常,關閉
currentEurekaClient
,後面要重新非返回 302 狀態碼的 Eureka-Server 。 - 第 10 行 :當前
currentHttpClient
不存在,意味着原有delegate
不存在向 Eureka-Server 成功請求的 EurekaHttpClient 。- 此時需要從配置中的 Eureka-Server 數組重試請求,獲得可以請求的 Eureka-Server 。
- 如果已經存在請求成功的
delegate
,直接使用它進行執行請求。
第 11 至 17 行 :調用
#getHostCandidates()
方法,獲得候選的 Eureka-ServerserviceUrls
數組。實現代碼如下:
1: private List<EurekaEndpoint> getHostCandidates() {2: // 獲得候選的 Eureka-Server 地址數組3: List<EurekaEndpoint> candidateHosts = clusterResolver.getClusterEndpoints();4:5: // 保留交集(移除 quarantineSet 不在 candidateHosts 的元素)6: quarantineSet.retainAll(candidateHosts);7:8: // 在保證最小可用的候選的 Eureka-Server 地址數組,移除在隔離集合內的元素9: // If enough hosts are bad, we have no choice but start over again10: int threshold = (int) (candidateHosts.size() * transportConfig.getRetryableClientQuarantineRefreshPercentage()); // 0.6611: if (quarantineSet.isEmpty()) {12: // no-op13: } else if (quarantineSet.size() >= threshold) {14: logger.debug("Clearing quarantined list of size {}", quarantineSet.size());15: quarantineSet.clear();16: } else {17: List<EurekaEndpoint> remainingHosts = new ArrayList<>(candidateHosts.size());18: for (EurekaEndpoint endpoint : candidateHosts) {19: if (!quarantineSet.contains(endpoint)) {20: remainingHosts.add(endpoint);21: }22: }23: candidateHosts = remainingHosts;24: }25:26: return candidateHosts;27: }- 第 3 行 :調用
ClusterResolver#getClusterEndpoints()
方法,獲得候選的 Eureka-Server 地址數組(candidateHosts
)。注意:該方法返回的 Eureka-Server 地址數組,使用以本機 IP 爲隨機種子,達到不同 IP 的應用實例獲得的數組順序不同,而相同 IP 的應用實例獲得的數組順序一致,效果類似基於 IP HASH 的負載均衡算法。實現該功能的代碼,在 《Eureka 源碼解析 —— EndPoint 與 解析器》搜索關鍵字【ResolverUtils#randomize(…)】 詳細解析。 - 第 6 行 :調用
Set#retainAll()
方法,移除隔離的故障 Eureka-Server 地址數組(quarantineSet
) 中不在candidateHosts
的元素。 - 第 8 至 24 行 :在保證最小可用的
candidateHosts
,移除在quarantineSet
的元素。- 第 10 行 :最小可用的閥值,配置
eureka.retryableClientQuarantineRefreshPercentage
來設置百分比,默認值:0.66
。 - 最 13 至 15 行 :
quarantineSet
數量超過閥值,清空quarantineSet
,全部candidateHosts
重試。 - 第 17 至 24 行 :
quarantineSet
數量未超過閥值,移除candidateHosts
中在quarantineSet
的元素。
- 第 10 行 :最小可用的閥值,配置
- 第 3 行 :調用
第 19 至 22 行 :超過
candidateHosts
上限,全部 Eureka-Server 請求失敗,拋出異常。
- 第 24 至 26 行 :創建委託的 EurekaHttpClient ,用於下面請求執行。
- 第 31 行 :執行請求。
第 33 行 :調用
ServerStatusEvaluator#accept()
方法,判斷響應狀態碼和請求類型是否能夠接受。實現代碼如下:
// ServerStatusEvaluators.javaprivate static final ServerStatusEvaluator LEGACY_EVALUATOR = new ServerStatusEvaluator() {public boolean accept(int statusCode, RequestType requestType) {if (statusCode >= 200 && statusCode < 300 || statusCode == 302) {return true;} else if (requestType == RequestType.Register && statusCode == 404) { // 註冊,404 可接受return true;} else if (requestType == RequestType.SendHeartBeat && statusCode == 404) { // 心跳,404 可接受return true;} else if (requestType == RequestType.Cancel) { // cancel is best effort 下線,接受全部return true;} else if (requestType == RequestType.GetDelta && (statusCode == 403 || statusCode == 404)) { // 增量獲取註冊信息,403 404 可接受return true;}return false;}};
第 34 行 :請求成功,設置
delegate
。下次請求,優先使用delegate
,失敗才進行候選的 Eureka-Server 地址數組重試。
- 第 47 行 :請求失敗,
delegate
若等於currentHttpClient
,進行清除。 - 第 50 至 52 行 :請求失敗,將請求的 Eureka-Server 地址添加到
quarantineSet
。 - 總結來說:
- 【第一步】若當前有請求成功的 EurekaHttpClient ,繼續使用。若請求失敗,執行【第二步】。
- 【第二步】若當前無請求成功的 EurekaHttpClient ,獲取候選的 Eureka-Server 地址數組順序創建新的 EurekaHttpClient,直到成功,或者超過最大重試次數。當請求成功,保存該 EurekaHttpClient ,下次繼續使用,直到請求失敗。
第 7 至 12 行 :超過當前會話時間,關閉當前委託的 EurekaHttpClient 。
第 10 行 :調用
#randomizeSessionDuration(...)
方法,計算計算下一次會話超時時長,公式爲sessionDurationMs * (0.5, 1.5)
,代碼如下:protected long randomizeSessionDuration(long sessionDurationMs) {long delta = (long) (sessionDurationMs * (random.nextDouble() - 0.5));return sessionDurationMs + delta;}- 增加會話過期的隨機性,實現所有 Eureka-Client 的會話過期重連的發生時間更加離散,避免集中時間過期。目前猜測這麼做的目的和 TODO[0028]:寫入集羣和讀取集羣 有關,即返回 302 。關聯 1.x new transport enhancements 。
第 15 至 18 行 :獲得委託的 EurekaHttpClient 。若不存在,創建新的委託的 EurekaHttpClient 。
TransportUtils#getOrSetAnotherClient(...)
方法代碼如下:
1: public static EurekaHttpClient getOrSetAnotherClient(AtomicReference<EurekaHttpClient> eurekaHttpClientRef, EurekaHttpClient another) {2: EurekaHttpClient existing = eurekaHttpClientRef.get();3: // 爲空才設置4: if (eurekaHttpClientRef.compareAndSet(null, another)) {5: return another;6: }7: // 設置失敗,意味着另外一個線程已經設置8: another.shutdown();9: return existing;10: }- 該方法實現,獲得
eurekaHttpClientRef
裏的 EurekaHttpClient 。若獲取不到,將another
設置到eurekaHttpClientRef
。當有多個線程設置時,有且只有一個線程設置成功,另外的設置失敗的線程們,意味着當前eurekaHttpClientRef
有 EurekaHttpClient ,返回eurekaHttpClientRef
。 目前該方法存在 BUG ,失敗的線程直接返回
existing
的是null
,需要修改成return eurekaHttpClientRef.get()
。模擬重現該 BUG 代碼如下 :
- 該方法實現,獲得
第 19 行 :執行請求。
第 18 至 27 行 :調用
Jersey1TransportClientFactories#newTransportClientFactory(...)
方法,創建registrationClient
和queryClient
公用的委託的 EurekaHttpClientFactory ,代碼如下:// Jersey1TransportClientFactories.javapublic TransportClientFactory newTransportClientFactory(final EurekaClientConfig clientConfig,final Collection<ClientFilter> additionalFilters,final InstanceInfo myInstanceInfo) {// JerseyEurekaHttpClientFactoryfinal TransportClientFactory jerseyFactory = JerseyEurekaHttpClientFactory.create(clientConfig,additionalFilters,myInstanceInfo,new EurekaClientIdentity(myInstanceInfo.getIPAddr()));// TransportClientFactoryfinal TransportClientFactory metricsFactory = MetricsCollectingEurekaHttpClient.createFactory(jerseyFactory); // 委託 TransportClientFactoryreturn new TransportClientFactory() {public EurekaHttpClient newClient(EurekaEndpoint serviceUrl) {return metricsFactory.newClient(serviceUrl);}public void shutdown() {metricsFactory.shutdown();jerseyFactory.shutdown();}};}- 在 TransportClientFactory 裏委託 JerseyEurekaHttpClientFactory 。
第 34 至 49 行 :調用
EurekaHttpClients#registrationClientFactory(...)
方法,創建registrationClient
的 EurekaHttpClientFactory ,代碼如下 :
// EurekaHttpClients.javapublic static EurekaHttpClientFactory registrationClientFactory(ClusterResolver bootstrapResolver,TransportClientFactory transportClientFactory,EurekaTransportConfig transportConfig) {return canonicalClientFactory(EurekaClientNames.REGISTRATION, transportConfig, bootstrapResolver, transportClientFactory);}static EurekaHttpClientFactory canonicalClientFactory(final String name,final EurekaTransportConfig transportConfig,final ClusterResolver<EurekaEndpoint> clusterResolver,final TransportClientFactory transportClientFactory) {return new EurekaHttpClientFactory() { // SessionedEurekaHttpClientFactorypublic EurekaHttpClient newClient() {return new SessionedEurekaHttpClient(name,RetryableEurekaHttpClient.createFactory( // RetryableEurekaHttpClientname,transportConfig,clusterResolver,RedirectingEurekaHttpClient.createFactory(transportClientFactory), // RedirectingEurekaHttpClientServerStatusEvaluators.legacyEvaluator()),transportConfig.getSessionedClientReconnectIntervalSeconds() * 1000);}public void shutdown() {wrapClosable(clusterResolver).shutdown();}};}
第 51 至 71 行 :調用
EurekaHttpClients#queryClientFactory(...)
方法,創建queryClient
的 EurekaHttpClientFactory ,代碼如下 :
// EurekaHttpClients.javapublic static EurekaHttpClientFactory queryClientFactory(ClusterResolver bootstrapResolver,TransportClientFactory transportClientFactory,EurekaClientConfig clientConfig,EurekaTransportConfig transportConfig,InstanceInfo myInstanceInfo,ApplicationsResolver.ApplicationsSource applicationsSource) {ClosableResolver queryResolver = transportConfig.useBootstrapResolverForQuery()? wrapClosable(bootstrapResolver): queryClientResolver(bootstrapResolver, transportClientFactory,clientConfig, transportConfig, myInstanceInfo, applicationsSource);return canonicalClientFactory(EurekaClientNames.QUERY, transportConfig, queryResolver, transportClientFactory); // 該方法上面有}
1. 概述
本文主要分享 Eureka 的網絡通信部分。在不考慮 Eureka 2.x 的兼容的情況下,Eureka 1.x 主要兩部分的網絡通信:
本文涉及類在 com.netflix.discovery.shared.transport
包下,涉及到主體類的類圖如下( 打開大圖 ):
類圖看起來很複雜,整體調用關係如下( 打開大圖 ):
OK ,我們逐層解析,嗨起來。
推薦 Spring Cloud 書籍:
2. EurekaHttpClient
com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient
,EurekaHttpClient 接口。接口代碼如下:
|
2.1 EurekaJerseyClientImpl
com.netflix.discovery.shared.transport.jersey.EurekaJerseyClientImpl
,EurekaHttpClient 實現類。實現代碼如下:
|
2.2 EurekaJerseyClientBuilder
EurekaJerseyClientBuilder ,EurekaJerseyClientImpl 內部類,用於創建 EurekaJerseyClientImpl 。
調用 #build()
方法,創建 EurekaJerseyClientImpl ,實現代碼如下:
|
3. EurekaHttpClient
com.netflix.discovery.shared.transport.EurekaHttpClient
,Eureka-Server HTTP 訪問客戶端,定義了具體的 Eureka-Server API 調用方法 。點擊 鏈接 查看帶中文註釋的 EurekaHttpClient。
3.1 EurekaHttpResponse
com.netflix.discovery.shared.transport.EurekaHttpResponse
,請求響應對象,實現代碼如下:
|
3.2 TransportClientFactory
com.netflix.discovery.shared.transport.TransportClientFactory
,創建 EurekaHttpClient 的工廠接口。接口代碼如下:
|
大多數 EurekaHttpClient 實現類都有其對應的工廠實現類。
4. AbstractJerseyEurekaHttpClient
com.netflix.discovery.shared.transport.jersey.AbstractJerseyEurekaHttpClient
,實現 EurekaHttpClient 的抽象類,真正實現了具體的 Eureka-Server API 調用方法。實現代碼如下:
|
4.1 JerseyApplicationClient
com.netflix.discovery.shared.transport.jersey.JerseyApplicationClient
,實現 Eureka-Client 請求 Eureka-Server 的網絡通信。點擊 鏈接 查看帶中文註釋的 JerseyApplicationClient。
4.1.1 JerseyEurekaHttpClientFactory
com.netflix.discovery.shared.transport.jersey.JerseyEurekaHttpClientFactory
,創建 JerseyApplicationClient 的工廠類。實現代碼如下:
|
4.1.2 JerseyEurekaHttpClientFactoryBuilder
JerseyEurekaHttpClientFactoryBuilder ,JerseyEurekaHttpClientFactory 內部類,用於創建 JerseyEurekaHttpClientFactory 。點擊 鏈接 查看帶中文註釋的 JerseyEurekaHttpClientFactory。
調用 JerseyEurekaHttpClientFactory#create(...)
方法,創建 JerseyEurekaHttpClientFactory ,實現代碼如下:
|
4.2 JerseyReplicationClient
com.netflix.eureka.transport.JerseyReplicationClient
,Eureka-Server 集羣內,Eureka-Server 請求 其它的Eureka-Server 的網絡通信。
4.2.1 沒有工廠
JerseyReplicationClient 沒有專屬的工廠。
調用 JerseyReplicationClient#createReplicationClient(...)
靜態方法,創建 JerseyReplicationClient 。點擊 鏈接 查看帶中文註釋的方法代碼。
5. EurekaHttpClientDecorator
com.netflix.discovery.shared.transport.decorator.EurekaHttpClientDecorator
,EurekaHttpClient 委託者抽象類。實現代碼如下:
|
EurekaHttpClientDecorator 的每個實現類實現一個特性,代碼非常非常非常清晰。
FROM 《委託模式》
委託模式是軟件設計模式中的一項基本技巧。在委託模式中,有兩個對象參與處理同一個請求,接受請求的對象將請求委託給另一個對象來處理。委託模式是一項基本技巧,許多其他的模式,如狀態模式、策略模式、訪問者模式本質上是在更特殊的場合採用了委託模式。委託模式使得我們可以用聚合來替代繼承,它還使我們可以模擬mixin。
我們在上圖的基礎上,增加委託的關係,如下圖( 打開大圖 ):
5.1 MetricsCollectingEurekaHttpClient
com.netflix.discovery.shared.transport.decorator.MetricsCollectingEurekaHttpClient
,監控指標收集 EurekaHttpClient ,配合 Netflix Servo 實現監控信息採集。
#execute()
方法,代碼如下:
|
5.2 RedirectingEurekaHttpClient
com.netflix.discovery.shared.transport.decorator.RedirectingEurekaHttpClient
,尋找非 302 重定向的 Eureka-Server 的 EurekaHttpClient 。
#execute()
方法,代碼如下:
|
5.2.1 工廠
RedirectingEurekaHttpClient 提供 #createFactory(...)
靜態方法獲得創建其的工廠,點擊 鏈接 查看。
5.3 RetryableEurekaHttpClient
com.netflix.discovery.shared.transport.decorator.RetryableEurekaHttpClient
,支持向多個 Eureka-Server 請求重試的 EurekaHttpClient 。
#execute()
方法,代碼如下:
|
5.3.1 工廠
RetryableEurekaHttpClient 提供 #createFactory(...)
靜態方法獲得創建其的工廠,點擊 鏈接 查看。
5.4 SessionedEurekaHttpClient
com.netflix.discovery.shared.transport.decorator.SessionedEurekaHttpClient
,支持會話的 EurekaHttpClient 。執行定期的重建會話,防止一個 Eureka-Client 永遠只連接一個特定的 Eureka-Server 。反過來,這也保證了 Eureka-Server 集羣變更時,Eureka-Client 對 Eureka-Server 連接的負載均衡。
#execute(...)
,代碼如下:
|
5.4.1 沒有工廠
在 SessionedEurekaHttpClient 類裏,沒有實現創建其的工廠。在 「6. 創建網絡通訊客戶端」搜索 canonicalClientFactory
,可以看到 EurekaHttpClients#canonicalClientFactory(...)
方法,內部有 SessionedEurekaHttpClient 的創建工廠。
6. 創建網絡通訊客戶端
對於 Eureka-Server 來說,調用 JerseyReplicationClient#createReplicationClient(...)
靜態方法即可創建用於 Eureka-Server 集羣內,Eureka-Server 請求 其它的Eureka-Server 的網絡通信客戶端。
對於 Eureka-Client 來說,分成用於註冊應用實例( registrationClient
)和查詢註冊信息( newQueryClient
)的兩個不同網絡通信客戶端。在 DiscoveryClient 初始化時進行創建,代碼如下:
|