https://blog.csdn.net/yuu1009/article/details/80776551
1. EurekaClient端发送请求
DiscoveryClient
- 在DiscoveryClient的构造方法的这段代码调用了register()方法进行注册
if (clientConfig.shouldRegisterWithEureka() && clientConfig.shouldEnforceRegistrationAtInit()) {
try {
// 发起一次注册操作
if (!register() ) {
// 启动时向EurekaServer注册失败
throw new IllegalStateException("Registration error at startup. Invalid server response.");
}
} catch (Throwable th) {
logger.error("Registration error at startup: {}", th.getMessage());
throw new IllegalStateException(th);
}
}
- DiscoveryClient中initScheduledTasks方法的instanceInfoReplicator
当实例信息发生改变的时,EurekaServer端发起注册操作, 这个由spring cloud netflix eureka 发起,
不是eureka-client发起。
既然InstanceInfoReplicator实现了Runnable,那么看一下run()方法,在run()方法中的discoveryClient.register()这一行向EurekaServer发起了注册请求,具体代码如下:
// InstanceInfo replicator
// 创建实例信息复制器,其实InstanceInfoReplicator继承了Runnable
// 详细操作看一下其中的run()方法,定时进行注册/刷新操作
instanceInfoReplicator = new InstanceInfoReplicator(
this,
instanceInfo,
// 默认30秒
clientConfig.getInstanceInfoReplicationIntervalSeconds(),
2); // burstSize
-----------------------
public void run() {
try {
// 定时刷新实例信息
discoveryClient.refreshInstanceInfo();
// 判断实例信息是否发生改变
// isInstanceInfoDirty默认为false,实例信息发生改变时会被设为true
// 被设为ture,则dirtyTimestamp不为null,则发起注册请求
Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
if (dirtyTimestamp != null) {
// 向EurekaServer注册
discoveryClient.register();
instanceInfo.unsetIsDirty(dirtyTimestamp);
}
} catch (Throwable t) {
logger.warn("There was a problem with the instance info replicator", t);
} finally {
// 定时执行本段逻辑
Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
scheduledPeriodicRef.set(next);
}
}
- register方法如下:
// 注册
boolean register() throws Throwable {
logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
EurekaHttpResponse httpResponse;
try {
// EurekaClient调用EurekaServer
// 通过AbstractJerseyEurekaHttpClient-register(instanceInfo)进行封装
// 调用到eureka-core包下的ApplicationResource-addInstance方法进行注册
httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
} catch (Exception e) {
logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
throw e;
}
if (logger.isInfoEnabled()) {
logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
}
return httpResponse.getStatusCode() == 204;
}
EurekaServer端接收请求
- ApplicationResource 类接受请求
这个类在eureka-core 包中,ApplicationResource .addInstance方法
@POST
@Consumes({"application/json", "application/xml"})
// 注册实例到EurekaServer
public Response addInstance(InstanceInfo info,
@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
logger.debug("Registering instance {} (replication={})", info.getId(), isReplication);
// validate that the instanceinfo contains all the necessary required fields
// 参数校验
if (isBlank(info.getId())) {
return Response.status(400).entity("Missing instanceId").build();
} else if (isBlank(info.getHostName())) {
return Response.status(400).entity("Missing hostname").build();
} else if (isBlank(info.getIPAddr())) {
return Response.status(400).entity("Missing ip address").build();
} else if (isBlank(info.getAppName())) {
return Response.status(400).entity("Missing appName").build();
} else if (!appName.equals(info.getAppName())) {
return Response.status(400).entity("Mismatched appName, expecting " + appName + " but was " + info.getAppName()).build();
} else if (info.getDataCenterInfo() == null) {
return Response.status(400).entity("Missing dataCenterInfo").build();
} else if (info.getDataCenterInfo().getName() == null) {
return Response.status(400).entity("Missing dataCenterInfo Name").build();
}
// handle cases where clients may be registering with bad DataCenterInfo with missing data
DataCenterInfo dataCenterInfo = info.getDataCenterInfo();
if (dataCenterInfo instanceof UniqueIdentifier) {
String dataCenterInfoId = ((UniqueIdentifier) dataCenterInfo).getId();
if (isBlank(dataCenterInfoId)) {
boolean experimental = "true".equalsIgnoreCase(serverConfig.getExperimental("registration.validation.dataCenterInfoId"));
if (experimental) {
String entity = "DataCenterInfo of type " + dataCenterInfo.getClass() + " must contain a valid id";
return Response.status(400).entity(entity).build();
} else if (dataCenterInfo instanceof AmazonInfo) {
AmazonInfo amazonInfo = (AmazonInfo) dataCenterInfo;
String effectiveId = amazonInfo.get(AmazonInfo.MetaDataKey.instanceId);
if (effectiveId == null) {
amazonInfo.getMetadata().put(AmazonInfo.MetaDataKey.instanceId.getName(), info.getId());
}
} else {
logger.warn("Registering DataCenterInfo of type {} without an appropriate id", dataCenterInfo.getClass());
}
}
}
// 进行注册并判断是否向其他EurekaServer节点进行注册信息传播
// EurekaServer既可以是同步信息操作的发起者也可以是同步信息请求的接收者
// isReplication为false的时候,为第一次请求,不向其他EurekaServer节点同步信息
// isReplication为true的时候,为其他EurekaServer节点向当前节发起同步信息请求
// 不过debug进去目测isReplication为null。。。
registry.register(info, "true".equals(isReplication));
return Response.status(204).build(); // 204 to be backwards compatible
}
PS: 若你觉得可以、还行、过得去、甚至不太差的话,可以“关注”一下,就此谢过!