1.首先,SpringCloud充分利用了SpringBoot的自动装配特色
eureka-server的jar包,发如今META-INF下面的配置文件spring.factories,里面记录了Spring Boot启动的时候会加载EurekaServerAutoConfiguration自动配置类
node
2.其次,分析EurekaServerAutoConfiguration类的源码,咱们发现该类的类头中存在@ConditionalOnBean的注解,如图
他表明的意思是,若是想要装配EurekaServerAutoConfigration,Spring容器中必需要有一个Marker的类的实例。
EurekaServerMarkerConfigration.Marker类:
咱们经过Find Usages功能查询,在什么样的状况下,咱们会向Spring容器中注入这个Marker对象
咱们发现,若是在Spring Cloud启动过程当中添加@EnableEurekaServer注解,咱们就会向容器中添加这个Marker的实例对象。也就是说,@EnableEurekaServer注解是Spring Cloud自动加载EurekaServerAutoConfiguration的控制开关。web
3.再次,咱们须要研究加载EurekaServerAutoConfigration类后,会向容器中注入那些Bean,有那些操做
经过structure结构图,咱们发现,EurekaServer类有一些自动逸的Codec实现,PeerEurekaNodes的回调接口。可是主要的,与EurekaServer启动相关的Bean有6个:EurekaController、PeerAuareInstanceRegistry、PeerEurekaNodes、EurekaServerContext、EurekaServerBootstrap、FilterRegistationBean。
3.1 EurekaController
注入一个对外的接口——仪表盘/后台界面,EurekaController。能够在配置文件中关闭它,可是默认是开启的状态。eureka.dashboard.enabled=true算法
3.2 PeerAuareInstanceRegistry 和 PeerEurekaNodes
PeerAwareInstanceRegistry是一个对等节点感知实例注册器(集群模式下注册服务使用到的注册器)。而且值得注意的是,EurekaServer集群模式中各个节点是对等的,没有主从之分。(这一点和Zookeeper不同,zk经过ZAB协议实现了分布式一致性,可是EurekaServer并无实现任何分布式算法)
PeerEurekaNodes是用来辅助封装对等节点相关的信息和操做,好比更新集群中的对等节点。
这里咱们稍微看下RefreshablePeerEurekaNodes的源码,咱们发现它是在继承PeerEurekaNodes的基础上实现了ApplicationListener接口,该接口只定义了一个回调方法,处理事件的回调
实际上,实例化RefreshablePeerEurekaNodes对象仍是经过父类的构造方法完成的,这个在代码的200行中有体现。spring
**3.3 **EurekaServerContext
向容器中注入了EurekaServerContext的对象,具体为DefaultEurekaServerContext。翻阅DefaultEurekaServerContext源码中,咱们发现它经过Spring的@PostConstruct注解调用了peerEurekaNodes对象的start()方法
具体在看一下64行调用的peerEurekaNodes.start()方法作了哪些操做
首先,定义了一个线程池Eureka-PeerNodesUpdater——Eureka的更新对等节点线程,最终start方法会开启这个线程,不停调用93行所指向的updatePeerEurekaNodes()方法。
这个updatePeerEurekaNodes()方法会更新对等节点信息,由于EurekaServer节点可能会不断的变化(好比,Eureka集群中某个节点的上下线)
而updatePeerEurekaNodes()方法主要作了什么呢?
其实就是Removing no longer available peer nodes和Adding new peer nodes。
至此,总结一下,EurekaServerContext的实例化过程,会启动更新远程对等节点的线程,不时的刷新远程对等节点的信息。安全
3.4 EurekaServerBootstrap
注入EurekaServerBootstrap对象,后续的EurekaServer应用的启动要依靠这个对象并发
3.5 FilterRegistrationBean
在Jersey框架下添加一个拦截器ServletContainer对象,拦截全部的/eureka/的请求,是的Jersey框架开始管理全部的/eureka/的请求框架
4.分析完EurekaServerAutoConfiguration具体注入哪些事情后,咱们在返回EurekaServerAutoConfiguration的类头分析
它利用的Spring的@Import注解,在EurekaServerAutoConfigration注入完全部的Bean后,再次调用了EurekaServerInitializerConfigration对象,装配了它。
因为EurekaServerInitializerConfiguration实现了SmartLifecycle接口,全部Spring容器的Bean建立完成后会回调start()方法。(顺便说一下,EurekaServerInitializerConfiguration类没有显式的无参方法,因此它的初始化会调用默认的无参构造方法,且几乎不会作什么操做)
而start()方法会开启一个后台线程去使用eurekaServerBootstrap对象初始化Context。分布式
4.1 分析eurekaServerBootstrap对象的contextInitialized()方法(在3.4步骤时实例化的)
初始化上下文实际上就是初始化环境变量方法的调用和初始化EurekaServerContext()方法。其中initEurekaEnvironment()方法就是读取配置,若是没有配置则设置成默认配置
再看看initEurekaServerContext()方法
这个方法中大致分为5步,1.注册序列化的转化器;2.对aws的状况进行特殊处理;3.为非IOC容器提供获取serverContext对象接口;4.从其余注册中心复制注册新信息;5.改变EurekaServer的状态,EurekaServer启动完成的标志
这里值得关注的是步骤4,如何复制其余节点的注册信息到本EurekaServer上。post
4.2 registry.syncUp()方法
这里224行的register()方法是作把远程得到过来的注册信息注册到本身的注册表中(map中)
register()方法中具体就是在保证线程安全的状况下对registry对象进行操做
综上所述,registry.syncUp()方法就是拷贝其余对等节点的注册信息到本身的注册表map中.net
4.3 registry.openForTraffic()方法
这里,咱们确定选择Peer的实现,由于Eureka Server的启动通常都是集群模式
openForTraffic()方法里,具体就是设置实例状态为UP,并调用父类的postInit()方法
在com.netflix.eureka.registry.AbstractInstanceRegistry#postInit()方法中,主要是启动失效剔除定时任务的,具体的任务逻辑在EvicationTask中定义。
这里调用了 AbstractInstanceRegistry的evict()方法
这个方法就是根据失效时常剔除失效的服务
综上所属,registry.syncUp()就是开启一个服务失效剔除线程
因此,
Eureka Server启动过程就是在@EnableEurekaServer开关的基础上,建立了一些后台进程去同步注册信息,并发布一个Jersey的web服务。它充分利用了Spring Boot的自动装配功能和spring的一些回调接口实现。