spring-eureka 在springCloud是類似於 zookeeper的存在,主要負責服務的注冊發現。
1 由於是Servlet應用,所以Eureka需要通過servlet的相關監聽器 ServletContextListener
嵌入到 Servlet 的生命周期中。EurekaBootStrap
類實現了該接口,在servlet標准的contextInitialized()
方法中完成了初始化工作:
@Override
public void contextInitialized(ServletContextEvent event) { try { // 讀取配置信息 initEurekaEnvironment(); // 初始化Eureka Client(用來與其它節點進行同步) // 初始化server initEurekaServerContext(); ServletContext sc = event.getServletContext(); sc.setAttribute(EurekaServerContext.class.getName(), serverContext); } catch (Throwable e) { logger.error("Cannot bootstrap eureka server :", e); throw new RuntimeException("Cannot bootstrap eureka server :", e); } }
2 與Spring Cloud結合的膠水代碼
Eureka是一個純正的Servlet應用,而Spring Boot使用的是嵌入式Tomcat, 因此就需要一定的膠水代碼讓Eureka跑在Embedded Tomcat中。這部分工作是在 EurekaServerBootstrap
中完成的。與上面提到的EurekaBootStrap
相比,它的代碼幾乎是直接將原生代碼copy過來的,雖然它並沒有繼承 ServletContextListener
, 但是相應的生命周期方法都還在,然后添加了@Configuration
注解使之能被Spring容器感知:
原生的 EurekaBootStrap
類實現了標准的ServletContextListener
接口
Spring Cloud的EurekaServerBootstrap
類沒有實現servlet接口,但是保留了接口方法的完整實現
我們可以推測,框架一定是在某處調用了這些方法,然后才是執行原生Eureka的啟動邏輯。EurekaServerInitializerConfiguration
類證實了我們的推測。該類實現了 ServletContextAware
(拿到了tomcat的ServletContext對象)、SmartLifecycle
(Spring容器初始化該bean時會調用相應生命周期方法):
@Configuration @CommonsLog public class EurekaServerInitializerConfiguration implements ServletContextAware, SmartLifecycle, Ordered { }
在 start()
方法中可以看到
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
的調用,也就是說,在Spring容器初始化該組件時,Spring調用其生命周期方法start()
從而觸發了Eureka的啟動。
@Override
public void start() {
new Thread(new Runnable() {
@Override
public void run() {
try { eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext); // 調用 servlet 接口方法手工觸發啟動 log.info("Started Eureka Server"); // ... ... } catch (Exception ex) { // Help! log.error("Could not initialize Eureka servlet context", ex); } } }).start(); }