Eureka Server源码解析(服务续约流程)

原创不易,转载请注明出处


前言

服务续约可以理解为心跳,客户端服务需要定时的向Eureka Server 发送续约请求,告诉Eureka Server 我这服务还活着,你别把我这个服务信息从注册表中剔除了。其实就是找到这个客户端实例对应的instance租约信息,更新一下最后更新时间。Eureka Server 有个后台任务,定时的去扫描注册表中的实例租约信息,看看更新时间与现在时间是不是隔了超过存活时间(默认是90s),如果超过了这个时间,就会将这个服务实例信息从注册表中剔除。

1.源码解析

客户端服务调用apps/{appName}/{instanceId} 路径发送续约请求。
Eureka Server接收服务续约请求是在InstanceResource 的renewLease 方法进行的。

@PUT
public Response renewLease(
        @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
        @QueryParam("overriddenstatus") String overriddenStatus,
        @QueryParam("status") String status,
        @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
    boolean isFromReplicaNode = "true".equals(isReplication);
    boolean isSuccess = registry.renew(app.getName(), id, isFromReplicaNode);
    // 此处省略若干行代码
    return response;
}

可以看到,调用了registry 注册表的renew 方法,参数1:appName ,参数2 instanceId,参数3,是否是服务集群其他节点同步请求,这个是与集群间同步相关的参数。
我们看看注册表PeerAwareInstanceRegistryImpl 的renew 方法

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;
}

分为2步,1是调用父类AbstractInstanceRegistry 的renew 方法,变更本地注册表服务实例租约信息,2是调用replicateToPeers 方法,将服务续约请求同步给集群的其他节点。这里我们只看下第一步的内容。

public boolean renew(String appName, String id, boolean isReplication) {
    RENEW.increment(isReplication);

    //根据appName 找到对应的实例租约列表
    Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
    Lease<InstanceInfo> leaseToRenew = null;
    if (gMap != null) {
        // 通过实例id (instanceId 获取对应实例的租约信息)
        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);
            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)) {
                logger.info(
                        "The instance status {} is different from overridden instance status {} for instance {}. "
                                + "Hence setting the status to overridden status", instanceInfo.getStatus().name(),
                                overriddenInstanceStatus.name(),
                                instanceInfo.getId());
                instanceInfo.setStatusWithoutDirty(overriddenInstanceStatus);

            }
        }
        // renew计数,自我保护机制会用到
        renewsLastMin.increment();
        // 实例
        leaseToRenew.renew();
        return true;
    }
}

这段代码核心流程就是通过 appName 与instanceId 实例id 获取对应实例的租约信息,然后就是 renewsLastMin.increment(); 增加renew 计数这个后面的自我保护机制会用到, 最后是调用租约信息的renew 方法进行实例续约,也就是执行leaseToRenew.renew()这行代码,return true。
我们来看下续约信息的renew方法。

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

其实就是更新lastUpdateTimestamp 这个字段。
将lastUpdateTimestamp 设置成 当前时间+ 过期间隔, 如果说一旦lastUpdateTimestamp 小于了当前时间,就说明这个实例租约过期了,这个实例可能会被Eureka Server 后台线程从注册表中剔除。

2.流程图

在这里插入图片描述

总结

本文主要是解析了一下Eureka Server处理服务续约请求的流程代码,当客户端进行服务注册之后,会有一个定时任务,默认是每30s 向Eureka Server端进行服务续约,也就是告诉Eureka Server 我这个客户端当前还活着,别给我从注册表中剔除了,服务续约其实就是心跳,如果是一段时间没有向Eureka Server 发送续约请求,就会被认为服务发生故障,故而从注册表中剔除。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

$码出未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值