SpringCloud-Eureka服务端之续约接口(8)

服务续约的作用

所谓的续约,其实不过一种健康检查的叫法,就是客户端告诉服务器端,我还活着。无论是zookeeper,nacos,eureka,还是各种监控系统,都存在着向服务器发送特殊信息标识自己依然存活,避免被剔除的命运。

服务续约

基于第七篇中注册接口的寻找方法,我们可以在Resource类中找到com.netflix.eureka.resources.InstanceResource#renewLease 续约接口

1.续约接口基本解析

通过下面一顿注解可以发现,主要在做两件事:

1.交给org.springframework.cloud.netflix.eureka.server.InstanceRegistry#renew继续进行续约操作

2.检查客户端传递的上次更新时间戳和服务器的时间戳是否不同(续约失败,同步失败,更新失败等造成)

public Response renewLease(
            @HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication,
            @QueryParam("overriddenstatus") String overriddenStatus,
            @QueryParam("status") String status,
            @QueryParam("lastDirtyTimestamp") String lastDirtyTimestamp) {
				// 1.是不是从其他节点复制过来的续约信息
        boolean isFromReplicaNode = "true".equals(isReplication);
				// 2.交给InstanceRegistry进一步注册
        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
	          // 当renew传入的上次客户端更新时间大于注册表中的上次更新时间时,表示中间存在未同步或者同步失败操作
						// 这时候需要同步客户端状态信息
						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;
    }

2.InstanceRegistry的renew之事件推送

在InstanceRegistry中做了个事件推送后,继续交给父类去renew

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IOzDZIWG-1606117118603)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7d0dcaf4-c4d5-4e55-9858-7a9f5b299e0f/Untitled.png)]


3.InstanceRegistry的父类之节点同步

com.netflix.eureka.registry.PeerAwareInstanceRegistryImpl#renew 中,再次将续约交给父类,自己做了个服务器集群节点复制

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZNrIoS85-1606117118607)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/39f964cc-3c1b-426e-9e2c-d476593ad255/Untitled.png)]

4.AbstractInstanceRegistry之正在的续约

com.netflix.eureka.registry.AbstractInstanceRegistry#renew 进行真正的注册,下面通过分析源码,总结大致流程:

1.从注册表中获取同服务名的集群信息,从集群中拿取续约实例

2.检查实例状态,更新续约检查时间

public boolean renew(String appName, String id, boolean isReplication) {
        RENEW.increment(isReplication);
				//1.通过应用名,从注册表中取出该应用的集群map信息
        Map<String, Lease<InstanceInfo>> gMap = registry.get(appName);
        Lease<InstanceInfo> leaseToRenew = null;
        if (gMap != null) {
						// 根据实例ID 从集群map中获取该实例的续约对象
            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(),
                                    instanceInfo.getOverriddenStatus().name(),
                                    instanceInfo.getId());
                    instanceInfo.setStatusWithoutDirty(overriddenInstanceStatus);

                }
            }
            renewsLastMin.increment();
						// 更新下次续约检查最后时间
            leaseToRenew.renew();
            return true;
        }
    }

总结

续约的过程比较简单,就是去更新InstanceInfo中的lastUpdateTimestamp。当然客户端状态还是要检查更新一下的。其流程基本跟注册一致。

到这里基本再去跟踪服务器端其他接口也就雷同了,后面不再花篇幅进行分析。

下面我们将进入Eureka客户端视角进行源码解读。

难的是开始,贵的是坚持,最后发现全是收获

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值