eureka源码解析——服务续约

本文详细剖析了Eureka服务续约过程,涉及InstanceResource的renewLease方法,以及PeerAwareInstanceRegistryImpl中renew和replicateToPeers的实现。核心内容包括客户端定时请求、服务端租约更新和集群同步策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

服务续约使用过心跳来实现了,客户端会开启一个定时任务,定时向eureka server发送续约请求,然后服务端收到续约信息然后更新租约的最后发送时间,在eureka server中也会开启一个定时任务,定时扫描注册表的实例租约信息,然后看最后续约时间距离现在是不是超过了存活时间(90s),如果超过了,就将这个实例从注册表中剔除

一、续约源码解析

1.1 InstanceResource#renewLease

客户端会发送续约请求,到服务端的处理接口就是renewLease接口,在这个接口中会调用注册表的renew方法来进行续约。

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

        // Not found in the registry, immediately ask for a register
        if (!isSuccess) {
            logger.warn("Not Found (Renew): {} - {}", app.getName(), id);
            return Response.status(Status.NOT_FOUND).build();
        }
        // Check if we need to sync based on dirty time stamp, the client
        // instance might have changed some value
        Response response;
        if (lastDirtyTimestamp != null && serverConfig.shouldSyncWhenTimestampDiffers()) {
            response = this.validateDirtyTimestamp(Long.valueOf(lastDirtyTimestamp), isFromReplicaNode);
            // Store the overridden status since the validation found out the node that replicates wins
            if (response.getStatus() == Response.Status.NOT_FOUND.getStatusCode()
                    && (overriddenStatus != null)
                    && !(InstanceStatus.UNKNOWN.name().equals(overriddenStatus))
                    && isFromReplicaNode) {
                registry.storeOverriddenStatusIfRequired(app.getAppName(), id, InstanceStatus.valueOf(overriddenStatus));
            }
        } else {
            response = Response.ok().build();
        }
        logger.debug("Found (Renew): {} - {}; reply status={}", app.getName(), id, response.getStatus());
        return response;
    }

1.2 PeerAwareInstanceRegistryImpl#renew

  1. 调用父类的AbstractInstanceRegistryrenew方法,更新本地注册表实例租约信息
  2. 调用replicateToPeers方法将服务续约请求同步给集群的其他节点
    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;
    }

1.2.1 AbstractInstanceRegistry#renew

这里就是更新注册表的租约信息,其实就是更新lastUpdateTimestamp

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

    //Lease#renew
    public void renew() {
        // 更新 lastUpdateTimestamp
        lastUpdateTimestamp = System.currentTimeMillis() + duration;

    }

1.2.2 PeerAwareInstanceRegistryImpl#replicateToPeers

这里就是遍历集群所有的其他节点,然后将实例信息同步到其他节点。

    private void replicateToPeers(Action action, String appName, String id,
                                  InstanceInfo info /* optional */,
                                  InstanceStatus newStatus /* optional */, boolean isReplication) {
        Stopwatch tracer = action.getTimer().start();
        try {
            if (isReplication) {
                numberOfReplicationsLastMin.increment();
            }
            // If it is a replication already, do not replicate again as this will create a poison replication
            if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
                return;
            }

            for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
                // If the url represents this host, do not replicate to yourself.
                if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
                    continue;
                }
                //复制实例信息到其他节点
                replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
            }
        } finally {
            tracer.stop();
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值