[Source learn together - Micro Services] Nexflix Eureka source VI: in dazzling code, EurekaClient is how to register?

Foreword

Last lecture already explained EurekaClient the startup process, there has to Eureka article 6 of the source code analysis, read the article before the next, feeling too much of code components will affect the reading, the latter will only interception of the main code, plus explain the comments.

This lecture is looking EurekaClient registration process, of course, a core, the title will be written on why the dazzling it? About Code EurekaClient registered, that is not so easily found.

Should the reprint please indicate the source: a flower count romantic

Source code analysis

If students read the previous article, will certainly know, Eureka Client finally start the process is to initialize DiscoveryClient this class, then we start the analysis directly from this class, after the code only interception of important codes, we can self-refer to a specific source.

DiscoveryClient.java

@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                Provider<BackupRegistry> backupRegistryProvider) {
    // 省略部分代码...

    this.applicationInfoManager = applicationInfoManager;
    // 创建一个配置实例,这里面会有eureka的各种信息,看InstanceInfo类的注释为:The class that holds information required for registration with Eureka Server 
    // and to be discovered by  other components.
    InstanceInfo myInfo = applicationInfoManager.getInfo();

    // 省略部分代码...
    

    try {
        // 支持底层的eureka client跟eureka server进行网络通信的组件
        eurekaTransport = new EurekaTransport();
        // 发送http请求,调用restful接口
        scheduleServerEndpointTask(eurekaTransport, args);
    } catch (Throwable e) {
        throw new RuntimeException("Failed to initialize DiscoveryClient!", e);
    }

    
    // 初始化调度任务
    initScheduledTasks();
}

Above omitted a lot of code, which also have mentioned in previous articles, to be honest here still see the look of nausea forced, entrance into the book in which it? No hurry, slowly analysis below.

DiscoveryClient.java

private void initScheduledTasks() {
    // 省略大部分代码,这段代码是初始化eureka client的一些调度任务

    // InstanceInfo replicator
    // 创建服务拷贝副本
    instanceInfoReplicator = new InstanceInfoReplicator(
            this,
            instanceInfo,
            clientConfig.getInstanceInfoReplicationIntervalSeconds(),
            2); // burstSize

    // 执行线程 InitialInstanceInfoReplicationIntervalSeconds默认为40s
    instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
}

DiscoveryClient is still above the source, we know the method name to see here is definitely related to the timing of task initialization EurekaClient started.
Here it is mainly intercepted instanceInfoReplicatorinitialization and execution of instanceInfoReplicator.starttasks,

Then we can take a look along this line InstatnceInfoReplicatoris the story behind?

/**
 * A task for updating and replicating the local instanceinfo to the remote server. Properties of this task are:
 * - configured with a single update thread to guarantee sequential update to the remote server
 * - update tasks can be scheduled on-demand via onDemandUpdate()
 * - task processing is rate limited by burstSize
 * - a new update task is always scheduled automatically after an earlier update task. However if an on-demand task
 *   is started, the scheduled automatic update task is discarded (and a new one will be scheduled after the new
 *   on-demand update).
 *
 * 用于将本地instanceinfo更新和复制到远程服务器的任务。此任务的属性是:
 * -配置有单个更新线程以保证对远程服务器的顺序更新
 * -可以通过onDemandUpdate()按需调度更新任务
 * -任务处理的速率受burstSize的限制
 * -新更新总是在较早的更新任务之后自动计划任务。但是,如果启动了按需任务*,则计划的自动更新任务将被丢弃(并且将在新的按需更新之后安排新的任务)
 */
class InstanceInfoReplicator implements Runnable {

}

There are two key points:

  1. This class implements Runnablean interface, it means an asynchronous execution threads
  2. This class action is: the local instanceinfo for updates and replication to a remote server tasks

After reading these two points, I can not help but fall into thinking, I am looking for eurekaClient registration process, which ye went to this coming? Reconciled, then read on.

InstanceInfoReplicator.start()

public void start(int initialDelayMs) {
    if (started.compareAndSet(false, true)) {
        instanceInfo.setIsDirty();  // for initial register
        Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
        scheduledPeriodicRef.set(next);
    }
}

This is a scheduled task scheduler thread pool, this thread will be put to the thread pool, and then execute the run method of this thread after a specified time.

InstanceInfoReplicator.run()

public void run() {
    try {
        // 刷新一下服务实例信息
        discoveryClient.refreshInstanceInfo();

        Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
        if (dirtyTimestamp != null) {
            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);
    }
}

See here is not the kind of suddenly feeling? Saw registerfelt hope here, used here is DiscoveryClient.register method, in fact, here we can find someone to register method DiscoveryClient, and then re-pegging the caller, this is a good idea to die.

DiscoveryClient.register

boolean register() throws Throwable {
    logger.info(PREFIX + appPathIdentifier + ": registering service...");
    EurekaHttpResponse<Void> httpResponse;
    try {
        // 回看eurekaTransport创建及初始化过程
        httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
    } catch (Exception e) {
        logger.warn("{} - registration failed {}", PREFIX + appPathIdentifier, e.getMessage(), e);
        throw e;
    }
    if (logger.isInfoEnabled()) {
        logger.info("{} - registration status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
    }
    return httpResponse.getStatusCode() == 204;
}

Here is the use eurekaTransport.registrationClient to register, we are at the beginning DiscoveryClient constructor has intercepted eurekaTransport creation and initialization code, paste it here:

// 支持底层的eureka client跟eureka server进行网络通信的组件
eurekaTransport = new EurekaTransport();
// 发送http请求,调用restful接口
scheduleServerEndpointTask(eurekaTransport, args);


private void scheduleServerEndpointTask(EurekaTransport eurekaTransport,
                                            AbstractDiscoveryClientOptionalArgs args) {

    // 省略大量代码

    // 如果需要抓取注册表,读取其他server的注册信息
    if (clientConfig.shouldRegisterWithEureka()) {
        EurekaHttpClientFactory newRegistrationClientFactory = null;
        EurekaHttpClient newRegistrationClient = null;
        try {
            newRegistrationClientFactory = EurekaHttpClients.registrationClientFactory(
                    eurekaTransport.bootstrapResolver,
                    eurekaTransport.transportClientFactory,
                    transportConfig
            );
            newRegistrationClient = newRegistrationClientFactory.newClient();
        } catch (Exception e) {
            logger.warn("Transport initialization failure", e);
        }
        // 将newRegistrationClient放入到eurekaTransport中
        eurekaTransport.registrationClientFactory = newRegistrationClientFactory;
        eurekaTransport.registrationClient = newRegistrationClient;
    }
}

To here, you can see eurekaTransport.registrationClient is in fact EurekaHttpClient, do not know is I did not find the right place or what, I did not find the specific implementation implementation class.

image.png

Finally, the online search, the implementation class specific implementation are:AbstractJersey2EurekaHttpClient

AbstractJersey2EurekaHttpClient.register()

public EurekaHttpResponse<Void> register(InstanceInfo info) {
        String urlPath = "apps/" + info.getAppName();
        Response response = null;
        try {
            // 发送请求,类似于:http://localhost:8080/v2/apps/ServiceA
            // 发送的是post请求,服务实例的对象被打成了一个json发送,包括自己的主机、ip、端口号
            // eureka server 就知道了这个ServiceA这个服务,有一个服务实例,比如是在192.168.31.109、host-01、8761端口
            Builder resourceBuilder = jerseyClient.target(serviceUrl).path(urlPath).request();
            addExtraProperties(resourceBuilder);
            addExtraHeaders(resourceBuilder);
            response = resourceBuilder
                    .accept(MediaType.APPLICATION_JSON)
                    .acceptEncoding("gzip")
                    .post(Entity.json(info));
            return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
        } finally {
            if (logger.isDebugEnabled()) {
                logger.debug("Jersey2 HTTP POST {}/{} with instance {}; statusCode={}", serviceUrl, urlPath, info.getId(),
                        response == null ? "N/A" : response.getStatus());
            }
            if (response != null) {
                response.close();
            }
        }
    }

To have the truth here, but read a pass code is found that it is difficult to understand, and finally summarize the wave of the job. . .

to sum up

(1) DiscoveryClient EurekaClient constructor initializes a timing related tasks, tasks scheduled task which will start another copy instanceInfo is InstanceInfoReplicator the start ()

(2) InstanceInfoReplicator the start () method which, itself as a thread into a scheduling thread pool to go, the default is to delay the implementation of this thread 40s, will isDirty set to ture

(3) If a thread of execution time is execution run () method, thread

(3) First find EurekaClient.refreshInstanceInfo () This method is, in fact, there are some methods of calling ApplicationInfoManager refreshes configuration service instance, look at the configuration has not changed, if changed, would refresh; a health check, and check a little state, the status is set to ApplicationInfoManager go, update service instance state

(4) as set isDirty had before, so there will be the implementation of the service registration

(5) Service registration when it is based on EurekaClient of reigster () method to register, the call is TransportClient of RegistrationClient underlying the implementation of the register () method, the information InstanceInfo service instance by http requests, call eureka server External exposure to a restful interface will InstanceInfo to send in the past. Here looking for a EurekaTransport, when constructed, called scheduleServerEndpointTask () method, which is initialized in the RegistrationClient specifically for registration.

(6) to find SessionedEurekaHttpClient call register () method to register, register end-use method of the underlying implementation of AbstractJersey2EurekaHttpClient

(7) eureka lot of jersey-based framework, provide restful interfaces on the eureka server, if you want to request eureka client sends a request to the eureka server, it must be based on the jersey framework, http restful interface to send calls

(8) the real implementation of a registration request, is the eureka-client-jersey2 project in the AbstractJersey2EurekaHttpClient, request http: // localhost: 8080 / v2 / apps / ServiceA, send the information service instances in the past

eureka client this piece, this piece of code is registered in the service, many slot points:

(1) registration service, should not be placed inside InstanceInfoReplicator, semantic uncertainty

HttpClient (2) is responsible for sending the request, the class system is too complicated, leading to people simply can not find the corresponding Client, and finally to restful interface exposes and calls based on his jersey is the use of the framework, in order to even Mongolia with a guess to find real send local service registration request

Declare

This article starting from my blog: https://www.cnblogs.com/wang-meng and public numbers: One ramiflorous be considered romantic , should reprint please indicate the source!

Interested partner may be concerned about the small number of individual public: One branch count romantic flowers

22.jpg

Guess you like

Origin www.cnblogs.com/wang-meng/p/12111342.html