Eureka实例自动过期
本文来说下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实例自动过期相关推荐
- Redis中的自动过期机制
实现需求:处理订单过期自动取消,比如下单30分钟未支付自动更改订单状态 实现方案1: 使用Redis Key自动过期出发事件通知 使用定时任务30分钟后检查 按照每分钟轮训检查 使用Redis Key ...
- php到期自动过期,PHP实现页面长时间无操作,自动过期函数
PHP实现页面长时间无操作,自动过期函数 发布于 2015-01-13 19:55:41 | 878 次阅读 | 评论: 0 | 来源: 网友投递 PHP开源脚本语言PHP(外文名: Hypertex ...
- java订单到期自动取消_订单自动过期实现方案
需求分析: 24小时内未支付的订单过期失效. 解决方案 被动设置:在查询订单的时候检查是否过期并设置过期状态. 定时调度:定时器定时查询并过期需要过期的订单. 延时队列:将未支付的订单放入一个延时队列 ...
- Redis 自动过期 使用 EXPIRE、PEXPIRE:设置生存时间
这里写目录标题 12.1 EXPIRE.PEXPIRE:设置生存时间 12.1.1 更新键的生存时间 12.1.2 其他信息 参考目录 12.1 EXPIRE.PEXPIRE:设置生存时间 用户可以通 ...
- Redis 自动过期 使用 SET命令的EX选项和PX选项
这里写目录标题 12.2 SET命令的EX选项和PX选项 12.2.1 组合命令的安全问题 12.2.2 其他信息 参考目录 12.2 SET命令的EX选项和PX选项 在使用键过期功能时,组合使用SE ...
- 咸鱼ZTMR实例—自动浇花器
咸鱼ZTMR实例-自动浇花器 我们之前用过土壤湿度计检测模块,继电器我们也会用了,还等什么呢?自动灌水安排上~ 主控板:ZTMR1.1开发板 土壤湿度计检测模块 模块介绍 采用优质土壤传感器做土壤湿度 ...
- java 自动过期缓存_Java自动过期本地缓存简单实现
实际项目中常常需要用到本地缓存,特别是一些固定不变的数据,不想频繁调接口,因为http请求本身需要耗时,下面几个类对本地缓存作了简单实现,支持自动过期功能 LocalCache.javainterfa ...
- Redis自动过期机制之key的过期监听(7)
Redis中的自动过期机制 前言 1.使用Redis Key自动过期机制 2.Springboot整合key过期监听 2.1. 创建表 order_number 2.2核心代码 2.2.1 核心代码 ...
- redis 存储数据不设置过期时间 会自动过期吗_Redis-数据淘汰策略持久化方式(RDB/AOF)Redis与Memcached区别...
Redis与Memcached区别: 两者都是非关系型数据库.主要有以下不同: 数据类型: Memcached仅支持字符串类型. redis支持:String,List,set,zset,hash 可 ...
最新文章
- 使用CA和CCA克隆账户
- 正式发布python版本的年份_飞书首次举办产品发布会,新版本“”正式发布
- visual studio2008 OpenGL开发配置
- 现代软件工程 第三章 【软件工程师的成长】练习与讨论
- 如何使用Linux重置Windows密码
- 开课吧Java课堂:什么是线程优先级?
- 几种实现ListView顶部悬浮效果
- 中文域名,网站,启用,弘勇,xn--2gr99z.xn--fiqs8s,网址,中国,
- 1,	定义一个基类BaseClass,从它派生出类DerivedClass。BaseClass里有成员函数fn1(),fn2(),DerivedClass也有成员函数fn1(),fn2()。在主函数中
- 怎样快速将方形图片剪裁成椭圆形?分享大家一个小妙招
- 计算机能力提升选网络研修,教师计算机能力提升个人研修计划
- Pytest测试框架(二):pytest 的setup/teardown方法
- Linux网络操作系统期末系统复习题
- Notification消息提醒
- 男人,你连剃须刀都不知道怎么选,活该你单身!
- MicroLib微库和ARM标准C库有什么区别?
- jquery 遍历集合
- 如何在行中统计满足条件的数据个数占比
- nanodet-plus
- Windos 快捷键的使用 windos 徽标键的妙用
热门文章
- Hyper-v下安装第一台Windows Server 2012 R2
- Google Maps API 申请方式变更为APIs Console, android手机申请方式
- 更多核心、更大内存、更低成本 AMD皓龙6000欲成云计算基石
- Q: 为什么如果我们把这两个组件安装在同一个COM+组件包中问题就不会出现(zz)...
- 塞班之死---放眼iOS的寒冬
- C#中委托和事件的区别
- jquery使用原型
- 使用tomcat8下的websocket进行web前后端通信
- Vb.net/VB 声明API功能父窗口功能
- 大哥你需求里说只要工作流引擎组件,怎么真正需要的东西这么.悲剧了,客户需求无止境...