1.源码定位
eureka server 接收服务器请求的处理方法为:
com.netflix.eureka.resources.InstanceResource#renewLease
源码版本: v1.7x
源码地址:https://github.com/Netflix/eureka/tree/v1.7.x
2.请求处理流程
- 从eureka server的注册表 registery中获取服务列表
registry.get(appName);
- 判断服务实例是否存在
leaseToRenew
,不存在则需要注册 - 判断服务实例状态是否存在,不存在说明需要重新注册
overriddenInstanceStatus
- 每份钟心跳数统计(剔除使用)
- 更新
Lease
心跳的最新更新时间 - 根据isReplication状态判断是否需要同步到其他eureka server
replicateToPeers
3.源码解析
public boolean renew(String appName, String id, boolean isReplication) {
RENEW.increment(isReplication);
// 从注册表中获取服务实例列表
Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
Lease<InstanceInfo> leaseToRenew = null;
if (gMap != null) {
// 根据服务实例id获取续约(心跳)信息
leaseToRenew = gMap.get(id);
}
if (leaseToRenew == null) {
RENEW_NOT_FOUND.increment(isReplication);
logger.warn("DS: Registry: lease doesn't exist, registering resource: {} - {}", appName, id);
return false;
} else {
InstanceInfo instanceInfo = leaseToRenew.getHolder();
if (instanceInfo != null) {
// touchASGCache(instanceInfo.getASGName());
// 根据规则计算服务实例状态
// 这里运用了一个责任链模式,将匹配规则放一个数组中
// 然后遍历这个数组,依次调用,返回首个匹配的状态。
InstanceStatus overriddenInstanceStatus = this.getOverriddenInstanceStatus(
instanceInfo, leaseToRenew, isReplication);
// 计算出来的服务实例状态为UNKNOEW 时,说明服务实例状态已被删除,需要重新注册
if (overriddenInstanceStatus == InstanceStatus.UNKNOWN) {
logger.info("Instance status UNKNOWN possibly due to deleted override for instance {}"
+ "; re-register required", instanceInfo.getId());
RENEW_NOT_FOUND.increment(isReplication);
return false;
}
// 如果计算出来的服务实例状态与当前服务实例状态不一致,那么就要覆写状态
if (!instanceInfo.getStatus().equals(overriddenInstanceStatus)) {
Object[] args = {
instanceInfo.getStatus().name(),
instanceInfo.getOverriddenStatus().name(),
instanceInfo.getId()
};
logger.info(
"The instance status {} is different from overridden instance status {} for instance {}. "
+ "Hence setting the status to overridden status", args);
// 覆盖状态
instanceInfo.setStatusWithoutDirty(overriddenInstanceStatus);
}
}
// 统计每分钟心跳数
renewsLastMin.increment();
// 服务实例心跳最后更新时间发布
leaseToRenew.renew();
return true;
}
}
public boolean renew(final String appName, final String id, final boolean isReplication) {
if (super.renew(appName, id, isReplication)) {
// 心跳续约成功则复制到其他对象上去
replicateToPeers(Action.Heartbeat, appName, id, null, null, isReplication);
return true;
}
return false;
}
4.小结
续约本身没有什么太多东西,就是修改注册表中Lease的续约时间,还有计算服务状态以及复制到集群其他节点。这里面比较有意思的一点竟然是服务状态计算使用了责任链模式。