Eureka客户端源码-服务注册&心跳机制
客户端注册流程
客户端向服务端发起注册一共有几个地方呢?
- 启动初始化的时候发起注册
- 发送心跳的时候如果服务端返回404,发起注册
- 客户端缓的存实例信息更新了,发起注册
注册流程客户端代码比较简单,发送post类型的http请求,请求参数为InstanceInfo
boolean register() throws Throwable {
EurekaHttpResponse httpResponse;
try {
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
throw e;
}
return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}
//AbstractJerseyEurekaHttpClient类中的方法
public EurekaHttpResponse register(InstanceInfo info) {
String urlPath = "apps/" + info.getAppName();
ClientResponse response = null;
try {
Builder resourceBuilder = jerseyClient.resource(serviceUrl).path(urlPath).getRequestBuilder();
addExtraHeaders(resourceBuilder);
response = resourceBuilder
.header("Accept-Encoding", "gzip")
.type(MediaType.APPLICATION_JSON_TYPE)
.accept(MediaType.APPLICATION_JSON)
.post(ClientResponse.class, info);
return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
}
}
客户端心跳
客户端定时向EurekaServer发送心跳信息 代码如下
private class HeartbeatThread implements Runnable {
public void run() {
//续约
if (renew()) {
//最后心跳成功的时间戳
lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
}
}
}
boolean renew() {
EurekaHttpResponse httpResponse;
try {
//发送put请求
httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(),
instanceInfo.getId(), instanceInfo, null);
//服务端响应404 则发起注册,
if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
REREGISTER_COUNTER.increment();
//标记本地的instanceInfo是脏的,返回最后设置脏标识的时间戳
long timestamp = instanceInfo.setIsDirtyWithTime();
//服务注册
boolean success = register();
if (success) {
//
instanceInfo.unsetIsDirty(timestamp);
}
return success;
}
return httpResponse.getStatusCode() == Status.OK.getStatusCode();
} catch (Throwable e) {
return false;
}
}
public synchronized void unsetIsDirty(long unsetDirtyTimestamp) {
//判断instanceInfo持有的lastDirtyTimestamp 小于登录 传入进行的时间戳
//判断的目的在于,还有其他的操作会设置脏标识 例如配置刷新的定时任务,如果客户端的instance配置更新了,
//则会把本地缓存的instanceInfo设置为脏标识 这个时候 lastDirtyTimestamp就更新了,
//这个时候实际上本地的instanceInfo和服务器上还不一致,所以还是脏的 所以不能重置 脏标识
if (lastDirtyTimestamp <= unsetDirtyTimestamp) {
isInstanceInfoDirty = false;
} else {
}
}