zoukankan      html  css  js  c++  java
  • EurekaServer自动装配及启动流程解析

    在开始本篇文章之前,我想你对SpringCloud和SpringBoot的基本使用已经比较熟悉了,如果不熟悉的话可以参考我之前写过的文章
    本篇文章的源码基于SpringBoot2.0,SpringCloud的Finchley.RELEASE

    @EnableEurekaServer注解

    我们知道,在使用Eureka作为注册中心的时候,我们会在启动类中增加一个@EnableEurekaServer注解,这个注解我们是一个自定义的EnableXXX系列的注解,主要作用我们之前也多次提到了,就是引入配置类而已。看一下源码吧

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

    引入了一个配置类EurekaServerMarkerConfiguration,看一下这个类的具体内容

    @Configuration
    public class EurekaServerMarkerConfiguration {
    
    	@Bean
    	public Marker eurekaServerMarkerBean() {
    		return new Marker();
    	}
    
    	class Marker {
    	}
    }
    

    现在看这里好像难以理解,这是啥意思,搞个空的类干啥的,不要着急,接着往下看

    自动装配

    既然注解上没有找到我们想要的东西,那么就看一下spring.factories文件吧,这里自动配置的实现类是EurekaServerAutoConfiguration

    由于这个类涉及的代码实在是太多了,这里就不贴了,咱们直接来解析这个类:

    1. 引入EurekaServerInitializerConfiguration类

    看名字就知道了这个类是负责Eureka的初始化工作的,这个类实现了SmartLifecycle接口,所以在spring初始化和销毁的时候,就会分别调用它的start和stop方法

    首先看一下start方法

    public void start() {
    		new Thread(new Runnable() {
    			@Override
    			public void run() {
    				try {
    					//启动EurekaServer
    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();
    	}
    

    这个代码好像比较直接了当啊,直接就起个线程启动了EurekaServer,然后发布了一些启动事件,来看启动的过程吧

    
    public void contextInitialized(ServletContext context) {
                    try {
                //初始化执行环境
                            initEurekaEnvironment();
                //初始化上下文
                            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);
                    }
            }
    

    这里一共包含初始化环境和初始化上下文两个分支

    初始化执行环境

    这个不是很重要,可以过滤掉

    
    protected void initEurekaEnvironment() throws Exception {
                    log.info("Setting the eureka configuration..");
                   //AWS相关的东西,可以忽略
                    String dataCenter = ConfigurationManager.getConfigInstance()
                                    .getString(EUREKA_DATACENTER);
                    if (dataCenter == null) {
                            log.info(
                                            "Eureka data center value eureka.datacenter is not set, defaulting to default");
                            ConfigurationManager.getConfigInstance()
                                            .setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, DEFAULT);
                    }
                    else {
                            ConfigurationManager.getConfigInstance()
                                            .setProperty(ARCHAIUS_DEPLOYMENT_DATACENTER, dataCenter);
                    }
            //设置 Eureka 环境,默认为test
                    String environment = ConfigurationManager.getConfigInstance()
                                    .getString(EUREKA_ENVIRONMENT);
                    if (environment == null) {
                            ConfigurationManager.getConfigInstance()
                                            .setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, TEST);
                            log.info(
                                            "Eureka environment value eureka.environment is not set, defaulting to test");
                    }
                    else {
                            ConfigurationManager.getConfigInstance()
                                            .setProperty(ARCHAIUS_DEPLOYMENT_ENVIRONMENT, environment);
                    }
            }
    
    初始化上下文
    
    protected void initEurekaServerContext() throws Exception {
                    // 设置json与xml序列化工具
                    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");
    
                    // 同步Eureka集群数据
                    int registryCount = this.registry.syncUp();
                    this.registry.openForTraffic(this.applicationInfoManager, registryCount);
    
                    // 注册监控统计信息
                    EurekaMonitors.registerAllStats();
            }
    

    这个方法中同步集群数据和注册监控信息都涉及的内容比较多,所以本篇文章就不再展开了,请关注我留意后续文章

    @ConditionalOnBean({Marker.class})

    看到这里就揭开了开篇@EnableEurekaServer注解注入的那个bean的含义了。也就是说如果咱们的启动类没有使用@EnableEurekaServer注解的话,这个自动配置类就不会执行,那也就没有Eureka的事了

    @EnableConfigurationProperties({EurekaDashboardProperties.class, InstanceRegistryProperties.class})

    深入这个注解发现这个还是使用的@Import注解的机制引入了两个类,这个注解在之前的源码解析文章中也多次提到了,这里就不展开了

    EurekaDashboardProperties这个类比较简单,主要是Eureka的控制台的相关配置

    //控制台默认路径
    private String path = "/";
    //是否开启控制台
    private boolean enabled = true;
    

    InstanceRegistryProperties,这个类是控制Eureka的注册时的配置信息

        //每分钟续约次数
        @Value("${eureka.server.expectedNumberOfRenewsPerMin:1}") 
    	private int expectedNumberOfRenewsPerMin = 1;
        //默认打开的通信数量
    	@Value("${eureka.server.defaultOpenForTrafficCount:1}")
    	private int defaultOpenForTrafficCount = 1;
    
    @PropertySource("classpath:/eureka/server.properties")

    相信大家比较熟悉这个注解,加载Eureka的配置文件而已

    配置文件中也仅仅只包含这个信息

    spring.http.encoding.force=false
    
    自动注入的bean

    EurekaServerAutoConfiguration类上几个注解就解析完了,接着看一下这个类中注入的几个比较重要的类吧

    配置类EurekaServerConfigBeanConfiguration

    EurekaServerConfig
    如果当前应用允许注册到其他Eureka服务中时,也就是属性eureka.client.fetch-registry为true时。就设置属性registrySyncRetries的值为5,这个属性的意思是当Eureka服务器启动时尝试去获取集群里其他服务器上的注册信息的次数

    EurekaController

    这个就是Eureka自己的controller了,控制台的相关信息就是从这里获取的

    ServerCodecs

    设置Eureka的序列化工具

    PeerAwareInstanceRegistry

    集群注册信息同步相关的类,请期待后续深入解析文章

    FilterRegistrationBean

    EurekaServer接受请求的一个拦截器,感兴趣的同学可以研究一下

  • 相关阅读:
    Fastjson
    react 使用createContext、Consumer 及 useContext 、Class.contextType父子组件共享数据
    使用useReducer 实现 todoList
    react中 useMemo与useCallback使用
    react17 函数组件 使用 better-scroll2.0 封装方法 及 使用
    react 执行 yarn build ,无法直接打开dist文件下的index
    react-redux 持久数据存储
    document.body.removeChild 获取到 symbol 标签
    react嵌套路由,并设置默认子路由
    Vagrant环境下配置node_exporter、mysqld_exporter、prometheus、grafana
  • 原文地址:https://www.cnblogs.com/zhixiang-org-cn/p/11657756.html
Copyright © 2011-2022 走看看