Spring Cloud Eureka服務運行流程原理


Eureka運行流程

流程描述

1,啟動過程分析

1.1   @EnableEurekaServer注解,來標記啟動注冊中心功能

@EnableDiscoveryClient
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(EurekaServerMarkerConfiguration.class)
public @interface EnableEurekaServer {

}

源碼中有2個重要的操作

1,使用注解@EnableDiscoveryClent,開啟SpringCloud服務發現客戶端的注解,由於SpringCloud在服務發現組件上不止支持Eureka,還支持例如Alibaba的Dubbo等。

2,Import(EurekaServerMarkerConfiguration.Class),導入配置類,此配置類還實例化了一個Marker的bean。

看下自動配置EurekaServerAutoConfiguration 源碼

@Configuration
@Import(EurekaServerInitializerConfiguration.class)
@ConditionalOnBean(EurekaServerMarkerConfiguration.Marker.class)
@EnableConfigurationProperties({ EurekaDashboardProperties.class,
        InstanceRegistryProperties.class })
@PropertySource("classpath:/eureka/server.properties")
public class EurekaServerAutoConfiguration extends WebMvcConfigurerAdapter {...

1)自動配置類實例化的前提是上下文中存在EurekaServerMarkerConfiguration.Marker這個bean

2)通過@EnableConfigurationProperties({ EurekaDashboardProperties.class, InstanceRegistryProperties.class })導入了兩個配置類

  EurekaDashboardProperties用於控制eureka面板的啟動及打開路徑。

  InstanceRegistryProperties 設置續約數量和通信數量

3)使用@Import導入配置類EurekaServerInitializerConfiguration.class

4)PropertySource控制字符集編碼的;

1.2  配置類EurekaServerAutoConfiguration

1)實例化bean

@Bean
    public HasFeatures eurekaServerFeature() {
        return HasFeatures.namedFeature("Eureka Server",
                EurekaServerAutoConfiguration.class);
    }

  2) 在靜態內部類中有條件的實例化了eureka服務端配置,配置類為 EurekaServerConfig;

@Configuration
    protected static class EurekaServerConfigBeanConfiguration {
        @Bean
        @ConditionalOnMissingBean
        public EurekaServerConfig eurekaServerConfig(EurekaClientConfig clientConfig) {
            EurekaServerConfigBean server = new EurekaServerConfigBean();
            if (clientConfig.shouldRegisterWithEureka()) {
                // Set a sensible default if we are supposed to replicate
                server.setRegistrySyncRetries(5);
            }
            return server;
        }
    }
View Code

  3)實例化了進入eureka控制面板的Controller類:EurekaController:用於展示eureka面板

@Bean
    @ConditionalOnProperty(prefix = "eureka.dashboard", name = "enabled", matchIfMissing = true)
    public EurekaController eurekaController() {
        return new EurekaController(this.applicationInfoManager);
    }
View Code

  4)eureka服務的Context維護

@Bean
    public EurekaServerContext eurekaServerContext(ServerCodecs serverCodecs,
            PeerAwareInstanceRegistry registry, PeerEurekaNodes peerEurekaNodes) {
        return new DefaultEurekaServerContext(this.eurekaServerConfig, serverCodecs,
                registry, peerEurekaNodes, this.applicationInfoManager);
    }

  5)實例化了eureka多個服務維持節點同步的bean;初始化注冊表

 @Bean
    public PeerAwareInstanceRegistry peerAwareInstanceRegistry(
            ServerCodecs serverCodecs) {
        this.eurekaClient.getApplications(); // force initialization
        return new InstanceRegistry(this.eurekaServerConfig, this.eurekaClientConfig,
                serverCodecs, this.eurekaClient,
                this.instanceRegistryProperties.getExpectedNumberOfRenewsPerMin(),
                this.instanceRegistryProperties.getDefaultOpenForTrafficCount());
    }

  6)管理每個eureka服務節點的生命周期

  @Bean
    @ConditionalOnMissingBean
    public PeerEurekaNodes peerEurekaNodes(PeerAwareInstanceRegistry registry,
            ServerCodecs serverCodecs) {
        return new PeerEurekaNodes(registry, this.eurekaServerConfig,
                this.eurekaClientConfig, serverCodecs, this.applicationInfoManager);
    }

  7)通過tomcat維護管理eureka生命周期

@Bean
    public EurekaServerBootstrap eurekaServerBootstrap(PeerAwareInstanceRegistry registry,
            EurekaServerContext serverContext) {
        return new EurekaServerBootstrap(this.applicationInfoManager,
                this.eurekaClientConfig, this.eurekaServerConfig, registry,
                serverContext);
    }

1.3  Eureka服務的啟動

  1)在EurekaServerBootstrap類中我們看到了初始化方法: 

 public void contextInitialized(ServletContext context) {
        try {

            //看源碼可知這里主要初始化服務環境,配置信息;
            initEurekaEnvironment();
           
            //初始化了eureka服務端的上下文
            initEurekaServerContext();

            context.setAttribute(EurekaServerContext.class.getName(), this.serverContext);
        }
        catch (Throwable e) {
            log.error("Cannot bootstrap eureka server :", e);
            throw new RuntimeException("Cannot bootstrap eureka server :", e);
        }
    }

  在這個方法中我們看到了初始化eureka-server環境配置及eureka-server上下文的操作,那么這個方法應該在一個地方有調用,通過查找調用發現:

@Configuration
@CommonsLog
public class EurekaServerInitializerConfiguration
        implements ServletContextAware, SmartLifecycle, Ordered {

   @Override
    public void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //TODO: is this class even needed now?
                     
eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
                    log.info("Started Eureka Server");

                    publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));
                    EurekaServerInitializerConfiguration.this.running = true;
                    publish(new EurekaServerStartedEvent(getEurekaServerConfig()));
                }
                catch (Exception ex) {
                    // Help!
                    log.error("Could not initialize Eureka servlet context", ex);
                }
            }
        }).start();
    }


    @Override
    public void stop() {
        this.running = false;
        eurekaServerBootstrap.contextDestroyed(this.servletContext);
    }

 ..... 部分代碼省略.....

}

  EurekaServerInitializerConfiguration中操作如下:

    1)start()初始化,

eurekaServerBootstrap.contextInitialized(EurekaServerInitializerConfiguration.this.servletContext);
                    log.info("Started Eureka Server");

    2)發布EurekaServer的注冊事件pubilsh

publish(new EurekaRegistryAvailableEvent(getEurekaServerConfig()));

    3)發布Eureka Start事件的pubilsh

publish(new EurekaServerStartedEvent(getEurekaServerConfig()));

    那么在啟動eureka服務有哪些操作呢?深入跟進下源碼.

 protected void initEurekaServerContext() throws Exception {
        // For backward compatibility
        JsonXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
                XStream.PRIORITY_VERY_HIGH);
        XmlXStream.getInstance().registerConverter(new V1AwareInstanceInfoConverter(),
                XStream.PRIORITY_VERY_HIGH);

        if (isAws(this.applicationInfoManager.getInfo())) {
            this.awsBinder = new AwsBinderDelegate(this.eurekaServerConfig,
                    this.eurekaClientConfig, this.registry, this.applicationInfoManager);
            this.awsBinder.start();
        }

        EurekaServerContextHolder.initialize(this.serverContext);

        log.info("Initialized server context");

        // Copy registry from neighboring eureka node
     //服務同步
int registryCount = this.registry.syncUp();
     //服務剔除
this.registry.openForTraffic(this.applicationInfoManager, registryCount); // Register all monitoring statistics. EurekaMonitors.registerAllStats(); }

           在初始化eureka服務端initEurekaServerContext()方法中,主要做了初始化server上下文,同步了其他節點的信息,啟動了剔除不可用eureka客戶端的定時任務;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM