【Java】Eureka - 服务续约和注册、下线(Server)

续约

续约的时候,调用的是服务端的InstanceResource#renewLease方法。调用的是InstanceRegistry.renew方法。

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

}

InstanceRegistry.renew会发一个EventPublish的续约监听(代码略),然后调用PeerAwareInstanceRegistryImpl#renew。PeerAwareInstanceRegistryImpl#renew。会调用AbstractInstanceRegistry#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;

}

AbstractInstanceRegistry#renew,获取续约,如果有的话。

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

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 {

// 其他略

renewsLastMin.increment();

leaseToRenew.renew();

return true;

}

}

Lease#renew,更新lastUpdateTimestamp时间。

public void renew() {

lastUpdateTimestamp = System.currentTimeMillis() + duration;

}

综上,续约就是更改lastUpdateTimestamp的时间。

注册

注册调用的是server的ApplicationResource#addInstance,他调用InstanceRegistry#register,和上面一样,这个会发布注册监听。

public Response addInstance(InstanceInfo info,

@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {

//其他略

registry.register(info, "true".equals(isReplication));

return Response.status(204).build(); // 204 to be backwards compatible

}

InstanceRegistry#register会调用PeerAwareInstanceRegistryImpl#register,实际的注册是AbstractInstanceRegistry#register方法,这个方法在Eureka - Server服务启动已经提过了,这里略。注册成功后,会进行节点间的复制。

@Override

public void register(final InstanceInfo info, final boolean isReplication) {

int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;

if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {

leaseDuration = info.getLeaseInfo().getDurationInSecs();

}

super.register(info, leaseDuration, isReplication);

replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);

}

下线

下线调用的是InstanceResource#cancelLease,然后他会调用InstanceRegistry#cancel(代码略)发布下线监听。

@DELETE

public Response cancelLease(

@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {

//其他略

boolean isSuccess = registry.cancel(app.getName(), id,

"true".equals(isReplication));

//其他略

}

InstanceRegistry#cancel调用PeerAwareInstanceRegistryImpl#cancel,下线成功后,会进行节点间的复制。

@Override

public boolean cancel(final String appName, final String id,

final boolean isReplication) {

if (super.cancel(appName, id, isReplication)) {

replicateToPeers(Action.Cancel, appName, id, null, null, isReplication);

return true;

}

return false;

}

AbstractInstanceRegistry#cancel会调用AbstractInstanceRegistry#internalCancel,这个是核心代码。这里会设置取消时间戳,并过期读写缓存。

@Override

public boolean cancel(String appName, String id, boolean isReplication) {

return internalCancel(appName, id, isReplication);

}

protected boolean internalCancel(String appName, String id, boolean isReplication) {

read.lock();

try {

//其他略

// 设置取消的时间戳

leaseToCancel.cancel();

//其他略

// 过期缓存,这里是读写缓存

invalidateCache(appName, vip, svip);

}

} finally {

read.unlock();

}

// 用于自我保护

synchronized (lock) {

if (this.expectedNumberOfClientsSendingRenews > 0) {

// Since the client wants to cancel it, reduce the number of clients to send renews.

this.expectedNumberOfClientsSendingRenews = this.expectedNumberOfClientsSendingRenews - 1;

updateRenewsPerMinThreshold();

}

}

return true;

}

另外,Eureka - Server服务启动提到了EvictionTask#run,他会清除过期的实例,他也会调用AbstractInstanceRegistry#internalCancel方法,所以读写缓存的图更改为:
【Java】Eureka - 服务续约和注册、下线(Server)

bug

我们看到,续约的时候lastUpdateTimestamp = System.currentTimeMillis() + duration;,判断是否过期的时候,又加了一个duration,所以他剔除的并不是90秒没有心跳的,而是180秒没有心跳的。

public boolean isExpired(long additionalLeaseMs) {

return (evictionTimestamp > 0 || System.currentTimeMillis() > (lastUpdateTimestamp + duration + additionalLeaseMs));

}

以上是 【Java】Eureka - 服务续约和注册、下线(Server) 的全部内容, 来源链接: utcz.com/a/93340.html

回到顶部