摘要: 原創出處 http://www.iocoder.cn/Eureka/eureka-server-init-second/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
本文主要基於 Eureka 1.8.X 版本
- 1. 概述
- 2. EurekaBootStrap
- 3. Filter
- 3.1 StatusFilter
- 3.2 ServerRequestAuthFilter
- 3.3 RateLimitingFilter
- 3.4 GzipEncodingEnforcingFilter
- 3.5 ServletContainer
- ServerConfig
- 【本文】EurekaBootStrap
- 請支持正版。下載盜版,等於主動編寫低級 BUG 。
- 程序猿DD —— 《Spring Cloud微服務實戰》
- 周立 —— 《Spring Cloud與Docker微服務架構實戰》
- 兩書齊買,京東包郵。
- 調用
#initEurekaEnvironment()
方法,初始化 Eureka-Server 配置環境。 - 調用
#initEurekaServerContext()
方法,初始化 Eureka-Server 上下文。 - 設置基於 Netflix Archaius 實現的配置文件的上下文,從而讀取合適的配置文件。大多數情況下,只需要設置
EUREKA_ENVIRONMENT
即可,不同的服務器環境( 例如,PROD
/TEST
等) 讀取不同的配置文件。實現原理,在《Eureka 源碼解析 —— Eureka-Client 初始化(一)之 EurekaInstanceConfig》「2.4 PropertiesInstanceConfig」有詳細解析。 - 感興趣的也可以閱讀:《Netflix Archaius 官方文檔 —— Deployment context》。
- 目前 Eureka-Server 提供 V2 版本 API ,如上代碼主要對 V1 版本 API 做兼容。可以選擇跳過。
- Eureka-Server 內嵌 Eureka-Client,用於和 Eureka-Server 集羣裏其他節點通信交互。
- Eureka-Client 的初始化過程,在《Eureka 源碼解析 —— Eureka-Client 初始化(三)之 EurekaClient》「3. DiscoveryClient」有詳細解析。
Eureka-Client 也可以通過 EurekaBootStrap 構造方法傳遞,實現代碼如下:
public class EurekaBootStrap implements ServletContextListener {private EurekaClient eurekaClient;public EurekaBootStrap(EurekaClient eurekaClient) {this.eurekaClient = eurekaClient;}}- 大多數情況下用不到。
應用實例信息的註冊表類關係圖如下:
本文不展開分享,在《Eureka 源碼解析 —— 註冊表 InstanceRegistry 類關係》詳細解析。
com.netflix.eureka.cluster.PeerEurekaNodes
,Eureka-Server 集羣節點集合,在《Eureka 源碼解析 —— Eureka-Server 集羣同步》詳細解析。com.netflix.eureka.EurekaServerContext
,Eureka-Server 上下文接口,提供Eureka-Server 內部各組件對象的初始化、關閉、獲取等方法。com.netflix.eureka.EurekaServerContext.DefaultEurekaServerContext
,Eureka-Server 上下文實現類,實現代碼如下:public class DefaultEurekaServerContext implements EurekaServerContext {/*** Eureka-Server 配置*/private final EurekaServerConfig serverConfig;/*** Eureka-Server 請求和響應編解碼器*/private final ServerCodecs serverCodecs;/*** 應用實例信息的註冊表*/private final PeerAwareInstanceRegistry registry;/*** Eureka-Server 集羣節點集合*/private final PeerEurekaNodes peerEurekaNodes;/*** 應用實例信息管理器*/private final ApplicationInfoManager applicationInfoManager;// .... 省略方法}com.netflix.eureka.EurekaServerContextHolder
,Eureka-Server 上下文持有者。通過它,可以很方便的獲取到 Eureka-Server 上下文,實現代碼如下:public class EurekaServerContextHolder {/*** 持有者*/private static EurekaServerContextHolder holder;/*** Eureka-Server 上下文*/private final EurekaServerContext serverContext;private EurekaServerContextHolder(EurekaServerContext serverContext) {this.serverContext = serverContext;}public EurekaServerContext getServerContext() {return this.serverContext;}/*** 初始化** @param serverContext Eureka-Server 上下文*/public static synchronized void initialize(EurekaServerContext serverContext) {holder = new EurekaServerContextHolder(serverContext);}public static EurekaServerContextHolder getInstance() {return holder;}}調用
ServerContext#initialize()
方法,初始化 Eureka-Server 上下文,實現代碼如下:// DefaultEurekaServerContext.javapublic void initialize() throws Exception {logger.info("Initializing ...");// 啓動 Eureka-Server 集羣節點集合(複製)peerEurekaNodes.start();// 初始化 應用實例信息的註冊表registry.init(peerEurekaNodes);logger.info("Initialized");}- 本文不展開分享,在 《Eureka 源碼解析 —— Eureka-Server 集羣同步》詳細解析。
- 配合 Netflix Servo 實現監控信息採集。
- StatusFilter
- ServerRequestAuthFilter
- RateLimitingFilter
- GzipEncodingEnforcingFilter
- ServletContainer
1. 概述
本文接《Eureka 源碼解析 —— Eureka-Server 啓動(一)之 EurekaServerConfig》,主要分享 Eureka-Server 啓動的過程的第二部分 —— EurekaBootStrap。
考慮到整個初始化的過程中涉及的代碼特別多,拆分成兩兩篇文章:
推薦 Spring Cloud 書籍:
2. EurekaBootStrap
com.netflix.eureka.EurekaBootStrap
,Eureka-Server 啓動入口。
EurekaBootStrap 實現了 javax.servlet.ServletContextListener
接口,在 Servlet 容器( 例如 Tomcat、Jetty )啓動時,調用 #contextInitialized()
方法,初始化 Eureka-Server,實現代碼如下:
|
2.1 初始化 Eureka-Server 配置環境
|
2.2 初始化 Eureka-Server 上下文
EurekaBootStrap 的 #initEurekaServerContext()
方法的實現代碼相對較多,已經將代碼切塊 + 中文註冊,點擊 EurekaBootStrap 鏈接,對照下面每個小結閱讀理解。
2.2.1 創建 Eureka-Server 配置
|
2.2.2 Eureka-Server 請求和響應的數據兼容
|
2.2.3 創建 Eureka-Server 請求和響應編解碼器
|
2.2.4 創建 Eureka-Client
|
2.2.5 創建應用實例信息的註冊表
|
2.2.6 創建 Eureka-Server 集羣節點集合
|
2.2.7 創建 Eureka-Server 上下文
|
2.2.8 初始化 EurekaServerContextHolder
|
2.2.9 初始化 Eureka-Server 上下文
|
2.2.10 從其他 Eureka-Server 拉取註冊信息
|
2.2.11 註冊監控
|
3. Filter
Eureka-Server 過濾器( javax.servlet.Filter
) 順序如下:
3.1 StatusFilter
com.netflix.eureka.StatusFilter
,Eureka-Server 狀態過濾器。當 Eureka-Server 未處於開啓( InstanceStatus.UP
)狀態,返回 HTTP 狀態碼 307 重定向,實現代碼如下:
|
3.2 ServerRequestAuthFilter
com.netflix.eureka.ServerRequestAuthFilter
,Eureka-Server 請求認證過濾器。Eureka-Server 未實現認證。目前打印訪問的客戶端名和版本號,配合 Netflix Servo 實現監控信息採集。實現代碼如下:
// ServerRequestAuthFilter.javaprotected void logAuth(ServletRequest request) {if (serverConfig.shouldLogIdentityHeaders()) {if (request instanceof HttpServletRequest) {HttpServletRequest httpRequest = (HttpServletRequest) request;String clientName = getHeader(httpRequest, AbstractEurekaIdentity.AUTH_NAME_HEADER_KEY);String clientVersion = getHeader(httpRequest, AbstractEurekaIdentity.AUTH_VERSION_HEADER_KEY);DynamicCounter.increment(MonitorConfig.builder(NAME_PREFIX + clientName + "-" + clientVersion).build());}}}
3.3 RateLimitingFilter
com.netflix.eureka.RateLimitingFilter
,請求限流過濾器。在《Eureka 源碼解析 —— 基於令牌桶算法的 RateLimiter》詳細解析。
3.4 GzipEncodingEnforcingFilter
com.netflix.eureka.GzipEncodingEnforcingFilter
,GZIP 編碼過濾器。
3.5 ServletContainer
com.sun.jersey.spi.container.servlet.ServletContainer
,Jersey MVC 請求過濾器。
Jersey MVC 模式如下圖:
FROM 《Jersey框架的MVC》
在
com.netflix.eureka.resources
包裏,有所有的 Eureka-Server Jersey Resource ( Controller )。過濾器在
web.xml
配置如下:<filter><filter-name>jersey</filter-name><filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class><init-param><param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name><param-value>/(flex|images|js|css|jsp)/.*</param-value></init-param><init-param><param-name>com.sun.jersey.config.property.packages</param-name><param-value>com.sun.jersey;com.netflix</param-value></init-param><!-- GZIP content encoding/decoding --><init-param><param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name><param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value></init-param><init-param><param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name><param-value>com.sun.jersey.api.container.filter.GZIPContentEncodingFilter</param-value></init-param></filter><filter-mapping><filter-name>jersey</filter-name><url-pattern>/*</url-pattern></filter-mapping>