Spring Cloud Eureka服务如何实现心跳续约机制?
- 内容介绍
- 文章标签
- 相关推荐
本文共计777个文字,预计阅读时间需要4分钟。
前言:Eureka Client的应用启动时,在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中,会执行以下几件事:
1. 周期性更新服务列表;
2.周期性续约服务;
3.服务注册逻辑;
4.概览信息。
前言
Eureka Client的应用启动时,在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中,会做以下几件事:
- 1、周期性更新服务列表;
- 3、周期性服务续约;
- 3、服务注册逻辑;
概览
以下图片来自Netflix官方,图中显示Eureka Client会发起Renew向注册中心做周期性续约,这样其他Eureka client通过Get Registry请求就能获取到新注册应用的相关信息:
来自官方文档的指导信息
最准确的说明信息来自Netflix的官方文档,地址: github.com/Netflix/eureka/wiki/Understanding-eureka-client-server-communication#renew
关于续约的理解:
- 1、Eureka client每隔三十秒发送一次心跳到Eureka server,这就是续约;
- 2、Eureka client续约的目的是告诉Eureka server自己还活着;
- 3、Eureka server若90秒内未收到心跳,就从自己的服务列表中剔除该Eureka client;
- 4、建议不要改变心跳间隔,因为Eureka server是通过心跳来判断Eureka client是否正常;
服务续约执行简要流程图
下面这张图大致描述了服务续约从Client端到Server端的大致流程,详情如下:
Eureka 续约源码分析
1、Eureka Client发起续约
Eureka Client向Eureka Server发起注册应用实例成功后获得租约,Eureka Client固定间隔向Eureka Server发起续约(renew),避免租约过期。
默认情况下,租约有效期为90秒,续约频率为30秒。两者比例为1:3,保证在网络异常等情况下,有三次重试的机会。
1)、初始化定时任务
Eureka Client在初始化过程中,创建心跳线程,固定间隔向Eureka Server发起续约。实现代码如下
@Singleton public class DiscoveryClient implements EurekaClient { /** * 初始化所有计划的任务 */ private void initScheduledTasks() { //获取注册信息的定时任务 if (clientConfig.shouldFetchRegistry()) { // registry cache refresh timer int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); cacheRefreshTask = new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() ); scheduler.schedule( cacheRefreshTask, registryFetchIntervalSeconds, TimeUnit.SECONDS); } if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs); //心跳定时任务 // Heartbeat timer heartbeatTask = new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ); scheduler.schedule( heartbeatTask, renewalIntervalInSecs, TimeUnit.SECONDS); //服务实例同步定时任务 // InstanceInfo replicator 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"); } } }2)、发起续约
@Singleton public class DiscoveryClient implements EurekaClient { //最后成功向Eureka Server心跳时间戳 private volatile long lastSuccessfulHeartbeatTimestamp = -1; private class HeartbeatThread implements Runnable { public void run() { // 调用续约方法 if (renew()) { lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis(); } } } //服务续约 boolean renew() { EurekaHttpResponse<InstanceInfo> xinchen.blog.csdn.net/article/details/82915355blog.csdn.net/qq_40378034/article/details/119079180
blog.csdn.net/NEW_BUGGER/article/details/93710797
www.cnblogs.com/liujunj/p/13401808.html
本文共计777个文字,预计阅读时间需要4分钟。
前言:Eureka Client的应用启动时,在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中,会执行以下几件事:
1. 周期性更新服务列表;
2.周期性续约服务;
3.服务注册逻辑;
4.概览信息。
前言
Eureka Client的应用启动时,在com.netflix.discovery.DiscoveryClient类的initScheduledTasks方法中,会做以下几件事:
- 1、周期性更新服务列表;
- 3、周期性服务续约;
- 3、服务注册逻辑;
概览
以下图片来自Netflix官方,图中显示Eureka Client会发起Renew向注册中心做周期性续约,这样其他Eureka client通过Get Registry请求就能获取到新注册应用的相关信息:
来自官方文档的指导信息
最准确的说明信息来自Netflix的官方文档,地址: github.com/Netflix/eureka/wiki/Understanding-eureka-client-server-communication#renew
关于续约的理解:
- 1、Eureka client每隔三十秒发送一次心跳到Eureka server,这就是续约;
- 2、Eureka client续约的目的是告诉Eureka server自己还活着;
- 3、Eureka server若90秒内未收到心跳,就从自己的服务列表中剔除该Eureka client;
- 4、建议不要改变心跳间隔,因为Eureka server是通过心跳来判断Eureka client是否正常;
服务续约执行简要流程图
下面这张图大致描述了服务续约从Client端到Server端的大致流程,详情如下:
Eureka 续约源码分析
1、Eureka Client发起续约
Eureka Client向Eureka Server发起注册应用实例成功后获得租约,Eureka Client固定间隔向Eureka Server发起续约(renew),避免租约过期。
默认情况下,租约有效期为90秒,续约频率为30秒。两者比例为1:3,保证在网络异常等情况下,有三次重试的机会。
1)、初始化定时任务
Eureka Client在初始化过程中,创建心跳线程,固定间隔向Eureka Server发起续约。实现代码如下
@Singleton public class DiscoveryClient implements EurekaClient { /** * 初始化所有计划的任务 */ private void initScheduledTasks() { //获取注册信息的定时任务 if (clientConfig.shouldFetchRegistry()) { // registry cache refresh timer int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); cacheRefreshTask = new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() ); scheduler.schedule( cacheRefreshTask, registryFetchIntervalSeconds, TimeUnit.SECONDS); } if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: {}", renewalIntervalInSecs); //心跳定时任务 // Heartbeat timer heartbeatTask = new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ); scheduler.schedule( heartbeatTask, renewalIntervalInSecs, TimeUnit.SECONDS); //服务实例同步定时任务 // InstanceInfo replicator 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"); } } }2)、发起续约
@Singleton public class DiscoveryClient implements EurekaClient { //最后成功向Eureka Server心跳时间戳 private volatile long lastSuccessfulHeartbeatTimestamp = -1; private class HeartbeatThread implements Runnable { public void run() { // 调用续约方法 if (renew()) { lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis(); } } } //服务续约 boolean renew() { EurekaHttpResponse<InstanceInfo> xinchen.blog.csdn.net/article/details/82915355blog.csdn.net/qq_40378034/article/details/119079180
blog.csdn.net/NEW_BUGGER/article/details/93710797
www.cnblogs.com/liujunj/p/13401808.html

