FROM 《深度剖析服务发现组件Netflix Eureka》
推荐 Spring Cloud 书籍:
请支持正版。下载盗版,等于主动编写低级 BUG 。
程序猿DD —— 《Spring Cloud微服务实战》
周立 —— 《Spring Cloud与Docker微服务架构实战》
两书齐买,京东包邮。
2. 为什么需要过期
正常情况下,应用实例下线时候会主动向 Eureka-Server 发起下线请求。但实际情况下,应用实例可能异常崩溃,又或者是网络异常等原因,导致下线请求无法被成功提交。
介于这种情况,通过 Eureka-Client 心跳延长租约,配合 Eureka-Server 清理超时的租约解决上述异常。
// AbstractInstanceRegistry.java
/**
* 清理租约过期任务
*/
private final AtomicReference evictionTaskRef = new AtomicReference();
protected void postInit() {
// …. 省略无关代码
// 初始化 清理租约过期任务
if (evictionTaskRef.get() != null) {
evictionTaskRef.get().cancel();
}
evictionTaskRef.set(new EvictionTask());
evictionTimer.schedule(evictionTaskRef.get(),
serverConfig.getEvictionIntervalTimerInMs(),
serverConfig.getEvictionIntervalTimerInMs());
}
配置 eureka.evictionIntervalTimerInMs ,清理租约过期任务执行频率,单位:毫秒。默认,60000 毫秒。
EvictionTask 实现代码如下:
class EvictionTask extends TimerTask {
@Override
public 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);
}
}
}
调用 #compensationTimeMs() 方法,获得补偿时间毫秒数。计算公式 = 当前时间 - 最后任务执行时间 - 任务执行频率。为什么需要补偿时间毫秒数,在 「4. 过期逻辑」Lease#isisExpired(additionalLeaseMs) 方法 揭晓。#compensationTimeMs() 实现代码如下:
/**
* 最后任务执行时间
*/
private final AtomicLong lastExecutionNanosRef = new AtomicLong(0L);
long getCompensationTimeMs() {
long currNanos = getCurrentTimeNano();
long lastNanos = lastExecutionNanosRef.getAndSet(currNanos);
if (lastNanos == 0L) {
return 0L;
}
long elapsedMs = TimeUnit.NANOSECONDS.toMillis(currNanos - lastNanos);
long compensationTime = elapsedMs - serverConfig.getEvictionIntervalTimerInMs();
return compensationTime <= 0L ? 0L : compensationTime;
}
由于 JVM GC ,又或是时间偏移( clock skew ) 等原因,定时器执行实际比预期会略有延迟。笔者在本机低负载运行,大概 10 ms 内。
compute a compensation time defined as the actual time this task was executed since the prev iteration, vs the configured amount of time for execution. This is useful for cases where changes in time (due to clock skew or gc for example) causes the actual eviction task to execute later than the desired time according to the configured cycle.
调用 #evict(compensationTime) 方法,执行清理过期租约逻辑,在 「4. 过期逻辑」 详细解析。
来源: http://geek.csdn.net/news/detail/242000