六、eureka客戶端自動注冊服務


所有文章

https://www.cnblogs.com/lay2017/p/11908715.html

 

正文

上一篇文章,我們稍微了解了一下eureka客戶端是如何自動配置的,配置了哪些東西。在自動配置的時候會產生一個負責自動注冊的Bean,也就是

@Bean
@ConditionalOnBean(AutoServiceRegistrationProperties.class)
@ConditionalOnProperty(
        value = "spring.cloud.service-registry.auto-registration.enabled",
        matchIfMissing = true)
public EurekaAutoServiceRegistration eurekaAutoServiceRegistration(
        ApplicationContext context, EurekaServiceRegistry registry,
        EurekaRegistration registration) {
    return new EurekaAutoServiceRegistration(context, registry, registration);
}

 

所以,我們打開EurekaAutoServiceRegistration看看

public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered, SmartApplicationListener {

    private ApplicationContext context;

    private EurekaServiceRegistry serviceRegistry;

    private EurekaRegistration registration;

    public EurekaAutoServiceRegistration(ApplicationContext context, EurekaServiceRegistry serviceRegistry, EurekaRegistration registration) {
        this.context = context;
        this.serviceRegistry = serviceRegistry;
        this.registration = registration;
    }

    @Override
    public void start() {
        // ...

        if (!this.running.get() && this.registration.getNonSecurePort() > 0) {

            // 調用注冊
            this.serviceRegistry.register(this.registration); this.context.publishEvent(new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig()));

            this.running.set(true);
        }
    }

}

 

注冊任務被委托給了serviceRegistry來做,跟進register方法

@Override
public void register(EurekaRegistration reg) {
    maybeInitializeClient(reg);

    // ...

    reg.getApplicationInfoManager().setInstanceStatus(reg.getInstanceConfig().getInitialStatus());

    reg.getHealthCheckHandler().ifAvailable(healthCheckHandler -> reg.getEurekaClient().registerHealthCheck(healthCheckHandler));
}

調用了eurekaClient原始的registerhealthCheck方法,跟進它

@Override
public void registerHealthCheck(HealthCheckHandler healthCheckHandler) {
    if (instanceInfo == null) {
        logger.error("Cannot register a healthcheck handler when instance info is null!");
    }
    if (healthCheckHandler != null) {
        // 注冊心跳檢查處理器
        this.healthCheckHandlerRef.set(healthCheckHandler);
        
        // schedule an onDemand update of the instanceInfo when a new healthcheck handler is registered
        if (instanceInfoReplicator != null) {
            instanceInfoReplicator.onDemandUpdate();
        }
    }
}

心跳檢查處理器被設置為了成員變量,執行的核心邏輯被托付給了onDemandUpdate方法,跟進它

public boolean onDemandUpdate() {
    if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {
        if (!scheduler.isShutdown()) {
            scheduler.submit(new Runnable() {
                @Override
                public void run() {
                    // ...
 InstanceInfoReplicator.this.run();
                }
            });
            return true;
        } else {
            // ... 
        }
    } else {
        // ...
    }
}

單線程異步執行了當前類的run方法,進入run方法

public void run() {
    try {
        // 刷新實例信息
 discoveryClient.refreshInstanceInfo();

        Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
        if (dirtyTimestamp != null) {
            // 注冊
 discoveryClient.register();
            instanceInfo.unsetIsDirty(dirtyTimestamp);
        }
    } catch (Throwable t) {
        // ...
    } finally {
        // 下一次延遲執行
        Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS); scheduledPeriodicRef.set(next);
    }
}

run方法每次執行都會刷新實例信息,然后調用register注冊新的實例信息,最后發出下一次執行的延遲任務

 

跟進register方法

boolean register() throws Throwable {
    logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
    EurekaHttpResponse<Void> httpResponse;
    try {
        // 發出遠程請求
        httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
    } catch (Exception e) {
        
    }
    
    return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
}

繼續跟進register方法,發出了http請求,這里以jersey為例

@Override
public EurekaHttpResponse<Void> 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)
                // 發出http請求
                .post(ClientResponse.class, info); return anEurekaHttpResponse(response.getStatus()).headers(headersOf(response)).build();
    } finally {
        if (logger.isDebugEnabled()) {
            logger.debug("Jersey HTTP POST {}/{} with instance {}; statusCode={}", serviceUrl, urlPath, info.getId(),
                    response == null ? "N/A" : response.getStatus());
        }
        if (response != null) {
            response.close();
        }
    }
}

http請求將進入eureka服務端,注冊實例信息有興趣可以看看eureka服務端注冊服務這篇。

 

總結

eureka客戶端自動注冊服務主要是將自動配置的時候拿到的實例信息通過http請求發送給eureka服務端,默認30秒會執行一次。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM