本文来说下Eureka实例自动过期

文章目录

  • 初始化配置
  • EvictionTask
  • Lease.isExpire()
  • 分批过期机制
  • 本文小结

初始化配置

在Eureka-Server启动的时候,会启动一个定时任务,用来清理过期的客户端

protected void initEurekaServerContext() throws Exception {// ....省略N多代码// 服务刚刚启动的时候,去其他服务节点同步客户端的数量。int registryCount = this.registry.syncUp();// 这个方法里面计算expectedNumberOfRenewsPerMin的值 , 重点在这里面,这里启动了清理任务的定时器this.registry.openForTraffic(this.applicationInfoManager, registryCount);// Register all monitoring statistics.EurekaMonitors.registerAllStats();}@Override
public void openForTraffic(ApplicationInfoManager applicationInfoManager, int count) {// ...省略N多代码// 开启定时清理过期客户端的定时器super.postInit();}protected void postInit() {renewsLastMin.start();if (evictionTaskRef.get() != null) {evictionTaskRef.get().cancel();}evictionTaskRef.set(new EvictionTask());// 设置定时器evictionTimer.schedule(evictionTaskRef.get(),serverConfig.getEvictionIntervalTimerInMs(),serverConfig.getEvictionIntervalTimerInMs());
}

renewsLastMin.start() : 在每个Eureka-Server端都维护着,每分钟的续约数量,续约数量是有一个Long类型的变量来存储的,每过一分钟就需要对这个变量进行清0 , 因此这个地方是为了启动这个线程。

 public synchronized void start() {if (!isActive) {timer.schedule(new TimerTask() {@Overridepublic void run() {try {// 进行清0lastBucket.set(currentBucket.getAndSet(0));} catch (Throwable e) {logger.error("Cannot reset the Measured Rate", e);}}}, sampleInterval, sampleInterval);isActive = true;}}

EvictionTask

是用来清理过期客户端的任务类。serverConfig.getEvictionIntervalTimerInMs() : 默认为60秒 , 可配置。

//EvictionTask class EvictionTask extends TimerTask {private final AtomicLong lastExecutionNanosRef = new AtomicLong(0l);@Overridepublic void run() {try {// 获取延迟秒数,就是延迟几秒下线long compensationTimeMs = getCompensationTimeMs();logger.info("Running the evict task with compensationTime {}ms", compensationTimeMs);evict(compensationTimeMs);} catch (Throwable e) {logger.error("Could not run the evict task", e);}}}public void evict(long additionalLeaseMs) {logger.debug("Running the evict task");// 判断是否开启自我保护机制if (!isLeaseExpirationEnabled()) {logger.debug("DS: lease expiration is currently disabled.");return;}List<Lease<InstanceInfo>> expiredLeases = new ArrayList<>();// 循环遍历本地CurrentHashMap中的实例信息for (Entry<String, Map<String, Lease<InstanceInfo>>> groupEntry : registry.entrySet()) {Map<String, Lease<InstanceInfo>> leaseMap = groupEntry.getValue();if (leaseMap != null) {for (Entry<String, Lease<InstanceInfo>> leaseEntry : leaseMap.entrySet()) {Lease<InstanceInfo> lease = leaseEntry.getValue();// 判断是否过期,此处为重点,里面有判断实例过期的依据if (lease.isExpired(additionalLeaseMs) && lease.getHolder() != null) {expiredLeases.add(lease);}}}}// 获取注册的实例数量int registrySize = (int) getLocalRegistrySize();// serverConfig.getRenewalPercentThreshold() 为0.85 , 主要是为了避免开启自动保护机制。 所以会逐步过期int registrySizeThreshold = (int) (registrySize * serverConfig.getRenewalPercentThreshold());// 可以过期的数量int evictionLimit = registrySize - registrySizeThreshold;// 取最小值,在过期数量和可以过期的数量中间取最小值。int toEvict = Math.min(expiredLeases.size(), evictionLimit);if (toEvict > 0) {logger.info("Evicting {} items (expired={}, evictionLimit={})", toEvict, expiredLeases.size(), evictionLimit);// 随机过期Random random = new Random(System.currentTimeMillis());for (int i = 0; i < toEvict; i++) {// Pick a random item (Knuth shuffle algorithm)int next = i + random.nextInt(expiredLeases.size() - i);Collections.swap(expiredLeases, i, next);Lease<InstanceInfo> lease = expiredLeases.get(i);String appName = lease.getHolder().getAppName();String id = lease.getHolder().getId();// 写入过期监控EXPIRED.increment();// 服务下线logger.warn("DS: Registry: expired lease for {}/{}", appName, id);internalCancel(appName, id, false);}}
}

Lease.isExpire()

//判断是否过期

public boolean isExpired(long additionalLeaseMs) {return (evictionTimestamp > 0 || System.currentTimeMillis() > (lastUpdateTimestamp + duration + additionalLeaseMs));
}

// 续约的时候会调用,用来更新最后更新时间

public void renew() {lastUpdateTimestamp = System.currentTimeMillis() + duration;
}

duration : 过期间隔,默认为90秒

evictionTimestamp : 实例下线时间,当客户端下线时,会更新这个时间。

lastUpdateTimestamp : 为最后更新时间 , 这里有个错误,因为续约的时候,更新这个时间的时候,加上了duration , 但是在最终做判断的时候

lastUpdateTimestamp + duration + additionalLeaseMs , 这个地方还加了一遍,也就导致了,当前时间必须要大于实际最后更新时间180秒,才会认为他过期 (撇开additionalLeaseMs这个因素不谈)


分批过期机制

从上面可以得知 , 这里有个分批过期的概念,每次最多过期15%的机器,超过15%则不会自动过期

假如检测到过期的实例数量为4台 , 总数量为10

执行过程过下:

第一个60秒到来,执行任务

int registrySize = 10 ;
int registrySizeThreshold = (int) (registrySize * 0.85) ;// 值为8
// 可以过期的数量
int evictionLimit = registrySize - registrySizeThreshold; //值为2

也就说仅仅只可以过期两台,那么另外两台怎么办,只能等待下一次任务执行的时候

第二个60秒到来,执行任务 , 计算是否开启保护机制时,这个时候呢,

numberOfRenewsPerMinThreshold还是原来的值,也就是 1020.85 = 17 , 但是由于

存活的机器数量只有6台,则每秒最大续约数为12 , 12>17 = false , 所以会开启自动保护机制

(如果在一分钟之类,另外两台机器恢复了心跳,16>17 , 依旧会开启),只能等待15分钟之后,定时任务重新计算这两个参数的值。

@Override
public boolean isLeaseExpirationEnabled() {// 是否开启自我保护机制,这是个配置,默认为trueif (!isSelfPreservationModeEnabled()) {return true;}// 计算是否下线return numberOfRenewsPerMinThreshold > 0 && getNumOfRenewsInLastMin() > numberOfRenewsPerMinThreshold;
}

开启自我保护机制之后,则不会继续往下执行了。

int registrySize = 8 ;
int registrySizeThreshold = (int) (registrySize * 0.85) ; //值为6
// 可以过期的数量
int evictionLimit = registrySize - registrySizeThreshold;// 值为2

总结: 由上可知,客户端具体的过期时间,是不确定的,但是必须大于180秒, 如果加上定时任务的时间间隔,240秒,

如果第一轮任务执行不到的话,可能会等到第二轮的时候执行,但是如果开启了自我保护机制,则没有第二轮的说法了。

如果不想启用这种机制,那么可以关闭自我保护机制,同时设置registrySizeThreshold = 0; 就可以一次性过期。


本文小结

本文详细介绍了Eureka实例自动过期相关的知识与内容。

Eureka实例自动过期相关推荐

  1. Redis中的自动过期机制

    实现需求:处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态 实现方案1: 使用Redis Key自动过期出发事件通知 使用定时任务30分钟后检查 按照每分钟轮训检查 使用Redis Key ...

  2. php到期自动过期,PHP实现页面长时间无操作,自动过期函数

    PHP实现页面长时间无操作,自动过期函数 发布于 2015-01-13 19:55:41 | 878 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertex ...

  3. java订单到期自动取消_订单自动过期实现方案

    需求分析: 24小时内未支付的订单过期失效. 解决方案 被动设置:在查询订单的时候检查是否过期并设置过期状态. 定时调度:定时器定时查询并过期需要过期的订单. 延时队列:将未支付的订单放入一个延时队列 ...

  4. Redis 自动过期 使用 EXPIRE、PEXPIRE:设置生存时间

    这里写目录标题 12.1 EXPIRE.PEXPIRE:设置生存时间 12.1.1 更新键的生存时间 12.1.2 其他信息 参考目录 12.1 EXPIRE.PEXPIRE:设置生存时间 用户可以通 ...

  5. Redis 自动过期 使用 SET命令的EX选项和PX选项

    这里写目录标题 12.2 SET命令的EX选项和PX选项 12.2.1 组合命令的安全问题 12.2.2 其他信息 参考目录 12.2 SET命令的EX选项和PX选项 在使用键过期功能时,组合使用SE ...

  6. 咸鱼ZTMR实例—自动浇花器

    咸鱼ZTMR实例-自动浇花器 我们之前用过土壤湿度计检测模块,继电器我们也会用了,还等什么呢?自动灌水安排上~ 主控板:ZTMR1.1开发板 土壤湿度计检测模块 模块介绍 采用优质土壤传感器做土壤湿度 ...

  7. java 自动过期缓存_Java自动过期本地缓存简单实现

    实际项目中常常需要用到本地缓存,特别是一些固定不变的数据,不想频繁调接口,因为http请求本身需要耗时,下面几个类对本地缓存作了简单实现,支持自动过期功能 LocalCache.javainterfa ...

  8. Redis自动过期机制之key的过期监听(7)

    Redis中的自动过期机制 前言 1.使用Redis Key自动过期机制 2.Springboot整合key过期监听 2.1. 创建表 order_number 2.2核心代码 2.2.1 核心代码 ...

  9. redis 存储数据不设置过期时间 会自动过期吗_Redis-数据淘汰策略持久化方式(RDB/AOF)Redis与Memcached区别...

    Redis与Memcached区别: 两者都是非关系型数据库.主要有以下不同: 数据类型: Memcached仅支持字符串类型. redis支持:String,List,set,zset,hash 可 ...

最新文章

  1. 使用CA和CCA克隆账户
  2. 正式发布python版本的年份_飞书首次举办产品发布会,新版本“”正式发布
  3. visual studio2008 OpenGL开发配置
  4. 现代软件工程 第三章 【软件工程师的成长】练习与讨论
  5. 如何使用Linux重置Windows密码
  6. 开课吧Java课堂:什么是线程优先级?
  7. 几种实现ListView顶部悬浮效果
  8. 中文域名,网站,启用,弘勇,xn--2gr99z.xn--fiqs8s,网址,中国,
  9. 1, 定义一个基类BaseClass,从它派生出类DerivedClass。BaseClass里有成员函数fn1(),fn2(),DerivedClass也有成员函数fn1(),fn2()。在主函数中
  10. 怎样快速将方形图片剪裁成椭圆形?分享大家一个小妙招
  11. 计算机能力提升选网络研修,教师计算机能力提升个人研修计划
  12. Pytest测试框架(二):pytest 的setup/teardown方法
  13. Linux网络操作系统期末系统复习题
  14. Notification消息提醒
  15. 男人,你连剃须刀都不知道怎么选,活该你单身!
  16. MicroLib微库和ARM标准C库有什么区别?
  17. jquery 遍历集合
  18. 如何在行中统计满足条件的数据个数占比
  19. nanodet-plus
  20. Windos 快捷键的使用 windos 徽标键的妙用

热门文章

  1. Hyper-v下安装第一台Windows Server 2012 R2
  2. Google Maps API 申请方式变更为APIs Console, android手机申请方式
  3. 更多核心、更大内存、更低成本 AMD皓龙6000欲成云计算基石
  4. Q: 为什么如果我们把这两个组件安装在同一个COM+组件包中问题就不会出现(zz)...
  5. 塞班之死---放眼iOS的寒冬
  6. C#中委托和事件的区别
  7. jquery使用原型
  8. 使用tomcat8下的websocket进行web前后端通信
  9. Vb.net/VB 声明API功能父窗口功能
  10. 大哥你需求里说只要工作流引擎组件,怎么真正需要的东西这么.悲剧了,客户需求无止境...