Spring Cloud Eureka核心源码分析-持续更新
前言
spring cloud是一个生态,它提供了一套标准,这套标准可以通过不同的组件来实现,其中就包含 服 务 注 册 / 发 现 、 熔 断 、 负 载 均 衡 等 , 在 spring-cloud-common 这 个 包 中 , org.springframework.cloud.client.serviceregistry 路径下,可以看到一个服务注册的接口定义ServiceRegistry 。它就是定义了spring cloud中服务注册的一个接口。我们可以看到,它有一个接口实现类EurekaServiceRegistry
用图说话--Eureka核心流程图
大图地址 www.processon.com/view/link/5…
1.Eureka服务注册的触发
服务的注册取决于服务是否已经启动好了,而在springboot中,会等到spring容器启动并且所有的配置都完成之后再进行注册。而这个动作在springboot的启动方法中的refreshContext中完成。
拓展--SmartLifeCycle知识
SmartLifeCycle是一个接口,当Spring容器加载完所有的Bean并且初始化之后,会继续回调实现了SmartLifeCycle接口的类中对应的方法,比如(start)。 实际上我们自己也可以拓展,比如在springboot工程的main方法同级目录下,写一个测试类,实现 SmartLifeCycle接口,并且通过@Service 声明为一个bean,因为要被spring去加载,首先得是bean。
接着,我们启动spring boot应用后,可以看到控制台输出了start 字符串。
我们在DefaultLifecycleProcessor.startBeans方法上加一个debug,可以很明显的看到我们自己定义的
TestSmartLifeCycle被扫描到了,并且最后会调用该bean的start方法。
在startBeans方法中,可以看到首先会获得所有实现了SmartLifeCycle的Bean,然后循环调用实现了SmartLifeCycle的bean的start方法,代码如下:
private void startBeans(boolean autoStartupOnly) {
Map<String, Lifecycle> lifecycleBeans = this.getLifecycleBeans();
Map<Integer, DefaultLifecycleProcessor.LifecycleGroup> phases = new HashMap();
lifecycleBeans.forEach((beanName, bean) -> {
if (!autoStartupOnly || bean instanceof SmartLifecycle && ((SmartLifecycle)bean).isAutoStartup()) {
int phase = this.getPhase(bean);
DefaultLifecycleProcessor.LifecycleGroup group = (DefaultLifecycleProcessor.LifecycleGroup)phases.get(phase);
if (group == null) {
group = new DefaultLifecycleProcessor.LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList(phases.keySet());
Collections.sort(keys);
Iterator var5 = keys.iterator();
while(var5.hasNext()) {
Integer key = (Integer)var5.next();
((DefaultLifecycleProcessor.LifecycleGroup)phases.get(key)).start();
}
}
}
public void start() {
if (!this.members.isEmpty()) {
if (DefaultLifecycleProcessor.this.logger.isDebugEnabled()) {
DefaultLifecycleProcessor.this.logger.debug("Starting beans in phase " + this.phase);
}
Collections.sort(this.members);
Iterator var1 = this.members.iterator();
while(var1.hasNext()) {
DefaultLifecycleProcessor.LifecycleGroupMember member = (DefaultLifecycleProcessor.LifecycleGroupMember)var1.next();
DefaultLifecycleProcessor.this.doStart(this.lifecycleBeans, member.name, this.autoStartupOnly);
}
}
}
DefaultLifeCycleProcessor.doStart()
private void doStart(Map<String, ? extends Lifecycle> lifecycleBeans, String beanName, boolean autoStartupOnly) {
Lifecycle bean = (Lifecycle)lifecycleBeans.remove(beanName);
if (bean != null && bean != this) {
String[] dependenciesForBean = this.getBeanFactory().getDependenciesForBean(beanName);
String[] var6 = dependenciesForBean;
int var7 = dependenciesForBean.length;
for(int var8 = 0; var8 < var7; ++var8) {
String dependency = var6[var8];
this.doStart(lifecycleBeans, dependency, autoStartupOnly);
}
if (!bean.isRunning() && (!autoStartupOnly || !(bean instanceof SmartLifecycle) || ((SmartLifecycle)bean).isAutoStartup())) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Starting bean '" + beanName + "' of type [" + bean.getClass().getName() + "]");
}
try {
bean.start();//此时Bean的实例应该是EurekaAutoServiceRegistration
} catch (Throwable var10) {
throw new ApplicationContextException("Failed to start bean '" + beanName + "'", var10);
}
if (this.logger.isDebugEnabled()) {
this.logger.debug("Successfully started bean '" + beanName + "'");
}
}
}
}
这里的bean.start()调用的是EurekaAutoServiceRegistration中的start方法,因为它实现了SmartLifeCycle接口。
public class EurekaAutoServiceRegistration implements AutoServiceRegistration,
SmartLifecycle, Ordered, SmartApplicationListener {
//去掉部分代码
@Override
public void start() {
// only set the port if the nonSecurePort or securePort is 0 and this.port != 0
if (this.port.get() != 0) {
if (this.registration.getNonSecurePort() == 0) {
this.registration.setNonSecurePort(this.port.get());
}
if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
this.registration.setSecurePort(this.port.get());
}
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
this.serviceRegistry.register(this.registration);
this.context.publishEvent(new InstanceRegisteredEvent<>(this,
this.registration.getInstanceConfig()));
this.running.set(true);
}
}
//去掉部分代码
}
这个start方法中,可以看到 this.serviceRegistry.register 这个方法,它实际上就是发起服务注册的机制。 此时this.serviceRegistry的实例,应该是 EurekaServiceRegistry , 原因是EurekaAutoServiceRegistration的构造方法中,会有一个赋值操作,而这个构造方法是在EurekaClientAutoConfiguration 这个自动装配类中被装配和初始化的,代码如下:
@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(
value = "spring.cloud.service-registry.auto-registration.enabled",
matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
ApplicationContext context, EurekaServiceRegistry registry,
EurekaRegistration registration) {
return new EurekaAutoServiceRegistration(context, registry, registration);
}
2.Eureka服务注册
我们开始分析服务注册流程。
EurekaAutoServiceRegistration.start
public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered, SmartApplicationListener {
@Override
public void start() {
// only set the port if the nonSecurePort or securePort is 0 and this.port != 0
if (this.port.get() != 0) {
if (this.registration.getNonSecurePort() == 0) {
this.registration.setNonSecurePort(this.port.get());
}
if (this.registration.getSecurePort() == 0 && this.registration.isSecure()) {
this.registration.setSecurePort(this.port.get());
}
}
// only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!this.running.get() && this.registration.getNonSecurePort() > 0) {
this.serviceRegistry.register(this.registration);
this.context.publishEvent(new InstanceRegisteredEvent<>(this,
this.registration.getInstanceConfig()));
this.running.set(true);
}
}
}
this.serviceRegistry.register(this.registration)方法最终会调用
EurekaServiceRegistry类中的register方法来实现服务注册。
EurekaServiceRegistry.register
@Override
public void register(EurekaRegistration reg) {
maybeInitializeClient(reg);
if (log.isInfoEnabled()) {
log.info("Registering application "
+ reg.getApplicationInfoManager().getInfo().getAppName()
+ " with eureka with status "
+ reg.getInstanceConfig().getInitialStatus());
}
//设置当前实例的状态,一旦这个实例的状态发生变化,只要状态不是DOWN,那么就会被监听器监听并 且执行服务注册。
reg.getApplicationInfoManager()
.setInstanceStatus(reg.getInstanceConfig().getInitialStatus());
//设置健康检查的处理
reg.getHealthCheckHandler().ifAvailable(healthCheckHandler -> reg
.getEurekaClient().registerHealthCheck(healthCheckHandler));
}
未完待续
3.Eureka Server端收到请求后的处理
待补充
4.知识点--Eureka 的多级缓存设计
待补充
5.知识点--服务续约
待补充
6.Eureka服务发现
待补充
7.Eureka Client如何查询地址
待补充
7.Eureka 服务端查询服务地址流程
待补充