智者不为愚者谋,勇者不为怯者死。这篇文章主要讲述:服务注册是如何发起的相关的知识,希望能为你提供帮助。
欢迎访问我的GitHub
- Spring Cloud环境下,服务提供者和消费者启动后都会将自身注册到Eureka,从本章开始我们来探寻整个注册过程的代码逻辑,以加深对Spring Cloud的服务注册发现机制的理解;
Eureka的服务注册发现功能涉及内容较多,因此分为多篇文章进行,大纲如下:
- 分析一个普通的SpringBoot应用,是如何开始执行服务注册发现相关的功能的,也就是本篇文章的内容;
- 分析服务列表的获取和更新逻辑;
- 分析注册到Eureka的逻辑;
- 分析向Eureka续租的逻辑;
- 一个SpringBoot应用如果要注册到Spring Cloud环境(Edgware.RELEASE版本),步骤很简单:
- pom.xml中添加启动器:spring-cloud-starter-netflix-eureka-client;
- 增加配置:eureka.client.serviceUrl.defaultZone: http://localhost:8081/eureka/;
- 启动应用;
- 如果注册中心正常,此时就能在注册中心发现这个应用了,如下图红框所示:
文章图片
为什么不用注解@EnableDiscoveryClient
- 在Edgware版本之前的Spring Cloud版本,需要在应用的配置类上添加注解@EnableDiscoveryClient,才会开启服务注册发现功能,但是自Edgware版本起,@EnableDiscoveryClient已成为可选项,不用该注解也能开启服务注册发现,参考《Spring Cloud源码分析之Eureka篇第三章:EnableDiscoveryClient与EnableEurekaClient的区别(Edgware版本)》;
- 现在就来分析应用启动过程,看注册服务是如何启动的:
- spring-cloud-netflix-eureka-client-1.4.0.RELEASE.jar是个重要的jar包,很多配置都在此jar内部的spring.factories文件中,首先要确定这个jar包是否会出现在应用的classpath中(如果不在classpath中,这些配置就不会生效),在pom.xml所在目录下执行命令==mvn dependency:tree==,打印依赖树,如下图,可确认spring-cloud-netflix-eureka-client被启动器spring-cloud-starter-netflix-eureka-client间接依赖,因此会出现在classpath中:
文章图片
- spring-cloud-netflix-eureka-client-1.4.0.RELEASE.jar是个重要的jar包,很多配置都在此jar内部的spring.factories文件中,首先要确定这个jar包是否会出现在应用的classpath中(如果不在classpath中,这些配置就不会生效),在pom.xml所在目录下执行命令==mvn dependency:tree==,打印依赖树,如下图,可确认spring-cloud-netflix-eureka-client被启动器spring-cloud-starter-netflix-eureka-client间接依赖,因此会出现在classpath中:
- spring-cloud-netflix-eureka-client-1.4.0.RELEASE.jar中的spring.factories文件,内容如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\ org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\\ org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\\ org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\\ org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\\ org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfiguration
- 以上配置信息可见,如果springboot启用了自动配置,那么EurekaClientConfigServerAutoConfiguration、......、EurekaDiscoveryClientConfiguration等五个配置类都会生效;3. 按照spring.factories中的配置,EurekaClientAutoConfiguration中的配置都会生效,包括下面这段代码返回的bean:
```java
@Bean
public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client)
return new EurekaDiscoveryClient(config, client);
- spring容器初始化时会实例化所有单例bean,就会执行EurekaClientAutoConfiguration的discoveryClient方法获取这个bean实例,于是就构造了一个EurekaDiscoveryClient对象;
- 注意EurekaDiscoveryClient的构造方法,第二个入参是com.netflix.discovery.EurekaClient类型,此对象同样来自EurekaClientAutoConfiguration类,如下方法:
@Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean(value = https://www.songbingjia.com/android/EurekaClient.class, search = SearchStrategy.CURRENT) @org.springframework.cloud.context.config.annotation.RefreshScope @Lazy public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) manager.getInfo(); // force initialization return new CloudEurekaClient(manager, config, this.optionalArgs,this.context);
- CloudEurekaClient的父类com.netflix.discovery.DiscoveryClient来自netflix发布的eureka-client包中,所以可以这么理解:EurekaDiscoveryClient类是个代理身份,真正的服务注册发现是委托给netflix的开源包来完成的,我们可以专心的使用SpringCloud提供的服务注册发现功能,只需要知道EurekaDiscoveryClient即可,真正的服务是eureka-client来完成的;
- 接下来需要关注com.netflix.discovery.DiscoveryClient的构造方法,因为这里面有服务注册的逻辑,整个构造方法内容太多,无需都细看,只看关键代码即可;
- DiscoveryClient的构造方法中,最熟悉的应该是下图红框中这段日志输出的了:
文章图片
- 对应的应用启动日志中就有这段日志输出,如下图红框:
文章图片
- 红框中的"
us-east-1"
,是默认的region,来自配置类EurekaClientConfigBean,这里面有各种eureka相关的配置信息,以及默认配置,如下图:
文章图片
- 继续看DiscoveryClient的构造方法,服务注册相关的initScheduledTasks方法在此被调用,如下图:
文章图片
- initScheduledTasks方法的内容如下,请注意中文注释:
private void initScheduledTasks() //获取服务注册列表信息 if (clientConfig.shouldFetchRegistry()) //服务注册列表更新的周期时间 int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); //定时更新服务注册列表 scheduler.schedule( new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() //该线程执行更新的具体逻辑 ), registryFetchIntervalSeconds, TimeUnit.SECONDS); if (clientConfig.shouldRegisterWithEureka()) //服务续约的周期时间 int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); //应用启动可见此日志,内容是:Starting heartbeat executor: renew interval is: 30 logger.info("Starting heartbeat executor: " + "renew interval is: " + renewalIntervalInSecs); // 定时续约 scheduler.schedule( new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() //该线程执行续约的具体逻辑 ), renewalIntervalInSecs, TimeUnit.SECONDS); //这个Runable中含有服务注册的逻辑 instanceInfoReplicator = new InstanceInfoReplicator( this, instanceInfo, clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2); // burstSizestatusChangeListener = new ApplicationInfoManager.StatusChangeListener() @Override public String getId() return "statusChangeListener"; @Override public void notify(StatusChangeEvent statusChangeEvent) if (InstanceStatus.DOWN == statusChangeEvent.getStatus() || InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) // log at warn level if DOWN was involved logger.warn("Saw local status change event ", statusChangeEvent); else logger.info("Saw local status change event ", statusChangeEvent); instanceInfoReplicator.onDemandUpdate(); ; if (clientConfig.shouldOnDemandUpdateStatusChange()) applicationInfoManager.registerStatusChangeListener(statusChangeListener); //服务注册 instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds()); else logger.info("Not registering with Eureka server per configuration");
- 上述代码中有几处需要注意,这些关键点在后面的章节将继续展开:
a. 周期性更新服务列表;
b. 周期性服务续约;
c. 服务注册逻辑被放入Runnable实现类InstanceInfoReplicator之中,在新线程中执行;
- 上述代码中有几处需要注意,这些关键点在后面的章节将继续展开:
- 在注册发现相关的内容中,Spring Cloud和Netflix的关系,可以用以下类图来辅助理解,该图来自大神< font color=" blue" > 程序猿DD< /font> 的文章《Spring Cloud源码分析(一)Eureka》,向大神致敬!
文章图片
- 至此,我们已经了解了SpringBoot应用启动服务注册功能的步骤,接下来的章节会继续深入如何更新服务列表;
推荐阅读
- CentOS8安装Geant4笔记(Geant4介绍编译和安装)
- Spring认证指南(了解如何使用 Gemfire 的数据结构构建应用程序)
- JavaScript 数据处理 - 映射表篇
- ZookeeperKafka 单机版安装
- Linux之traceroute命令
- Spring源码之七registerListeners()及发布订阅模式
- C语言函数中的传值和传址
- Win10(64)专业版电脑如何修改时间
- linux网络第一周作业