6. eureka client 与server的服务注册

https://blog.csdn.net/yuu1009/article/details/80776551

1. EurekaClient端发送请求

DiscoveryClient

  1. 在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);
    }
}
  1. 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);
    }
}

  1. 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端接收请求

  1. 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: 若你觉得可以、还行、过得去、甚至不太差的话,可以“关注”一下,就此谢过!

你可能感兴趣的:(6. eureka client 与server的服务注册)