Eureka Server启动流程
eureka-core组件下
EurekaBootStrap类详解
//初始化Eureka环境
initEurekaEnvironment();
(1)创建一个ConcurrentCompositeConfiguration实例,就是代表了eureka需要的所有的配置。在初始化这个实例的时候,调用了clear()方法,fireEvent发布了事件(EVENT_CLEAR),fireEvent()这个方法是父类的方法
(2)往ConcurrentCompositeConfiguration实例加入一堆别的config,就返回了实例,就是作为所谓的那个配置的单例
(3)初始化数据中心的配置,如果没有配置,就是DEFAULT data center
(4)实例化eureka运行的环境,如果没有配置,默认就给你设置为test环境
(5)initEurekaEnvironment的初始化环境的逻辑就结束了
重点理解:
ConfigurationManager的单例初始化的过程,使用到了double check +volatile的单例实现模式。
初始化环境的逻辑,主要是初始化 数据中心 + 运行环境 ,没设置的话,给设置成默认的和测试。
//初始化eureka-server上下文(context)
initEurekaServerContext();
加载eureka-server,properties的过程
(1)创建一个DefaultEurekaServerConfig对象
(2)创建DefaultEurekaServerConfig对象的时候,里面会有个init方法
(3)显示将eureka-server.properties中的配置加载到一个Properties对象中,然后将Properties对象中的配置放到ConfigurationManager中去,此时ConfigurationManager中就有了所有的配置。
(4)然后DefaultEurekaServerConfig提供的获取配置项的各个方法,都是通过硬编码的配置项名称,从DynamicPropertyFactory中获取配置项的值,DynamicPropertyFactory是从ConfigurationManager来的,所以也包含了所有配置项的值。
(5)在获取配置项的时候,如果没有配置,那么就会有默认的值,全部属性都是有默认值的。
加载eureka-client,properties的过程
(1)加载eureka-client.properties文件的配置,对外提供EurekaInstanceConfig接口的逻辑
(2)基于构造器模式完成的InstanceInfo(服务实例)的构造的一个过程
(3)EurekaInstanceConfig(代表了一些配置),搞了InstanceInfo(服务实例),基于这俩玩意儿,搞了一个ApplicationInfoManager,作为服务实例的一个管理器
构建一个eurekaClient,以DiscoveryClient这个类来构建
(1)读取EurekaCLientConfig,包括TransportConfig
(2)保存EurekaInstanceConfig和InstanceInfo
(3)处理是否要注册以及抓取注册表,如果不要的话,释放一些资源
(4)支持调度的线程池
(5)支持心跳的线程池
(6)支持缓存刷新的线程池
(7)EurekaTransport,支持底层的eureka client跟eureka server进行网络通信的组件,对网络通信组件进行初始化操作
(8)如果要抓取注册表,接下来执行抓取操作,如果配置了不抓取,这里就不抓去了
(9)初始化调度任务,如果要抓取注册表的,就会注册一个按你设定的抓取的间隔(默认30s),去执行一个CacheRefreshThread,给放进调度线程池里面去。如果要向eureka server注册的话,会弄一个定时任务,每隔一定时间(默认30s)发送心跳,执行一个HeartbeatThread。创建一个服务实例副本传播器,将自己作为一个定时任务进行调度。创建一个服务实例的状态变更监听器。如果配置了监听,那么就会注册监听器。
剩余初始化的步骤
(1)构造了一个东西:PeerAwareInstanceRegistry
PeerAware,可以识别eureka server集群的:peer,多个同样的东西组成的一个集群,peers集群,peer就是集群中的一个实例
InstanceRegistry:实例注册,服务实例注册,注册表,这个里面放了所有的注册到这个eureka server上来的服务实例,就是一个服务实例的注册表
PeerAwareInstanceRegistry:可以感知eureka server集群的服务实例注册表,eureka client(作为服务实例)过来注册的注册表,而且这个注册表是可以感知到eureka server集群的。假如有一个eureka server集群的话,这里包含了其他的eureka server中的服务实例注册表的信息的。
(2)构造了一个东西:PeerEurekaNodes
猜,PeerEurekaNodes,代表了eureka server集群,peers大概来说多个相同的实例组成的一个集群,peer就是peers集群中的一个实例,PeerEurekaNodes,大概来说,猜测,应该是代表的是eureka server集群
(3)构造了一个东西:EurekaServerContext
将上面构造好的所有的东西,都一起来构造一个EurekaServerContext,代表了当前这个eureka server的一个服务器上下文,包含了服务器需要的所有的东西。将这个东西放在了一个holder中,以后谁如果要使用这个EurekaServerContext,直接从这个holder中获取就可以了。这个也是一个比较常见的用法,就是将初始化好的一些东西,放在一个holder中,然后后面的话呢,整个系统运行期间,谁都可以来获取,在任何地方任何时间,谁都可以获取这个上下文,从里面获取自己需要的一些组件。
(4)EurekaServerContext.initialize()
peerEurekaNodes.start();
这里呢,就是将eureka server集群给启动起来,更新一下eureka server集群的信息,让当前的eureka server感知到所有的其他的eureka server。然后搞一个定时调度任务,就一个后台线程,每隔一定的时间,更新eureka server集群的信息。
registry.init(peerEurekaNodes);
基于eureka server集群的信息,来初始化注册表,将eureka server集群中所有的eureka server的注册表的信息,都抓取过来,放到自己本地的注册表里去,多是跟eureka server集群之间的注册表信息互换有关联的
(5)registry.syncUp();
从相邻的一个eureka server节点拷贝注册表的信息,如果拷贝失败,就找下一个
(6)EurekaMonitors.registerAllStats();
跟eureka自身的监控机制相关联的。
Eureka Server启动流程图