Spring Cloud Eureka核心源码分析-持续更新

98 阅读2分钟

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 服务端查询服务地址流程

待补充