这篇文章主要介绍了SpringCloud Eureka 服务注册实现过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
一、将服务注册到Eureka
一个SpringBoot应用如果要注册到Spring Cloud环境(Greenwich.SR3版本),步骤很简单:pom.xml中添加启动器:spring-cloud-starter-netflix-eureka-client;增加配置:eureka.client.serviceUrl.defaultZone: http://localhost:8100/eureka/;启动应用;如果注册中心正常,此时就能在注册中心发现这个应用了,如下图红框所示:按照spring.factories中的配置,EurekaClientAutoConfiguration中的配置都会生效,包括下面这段代码返回的bean:@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 = 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); // burstSize statuschangelistener = 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之中,在新线程中执行;版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。