Eureka服務註冊

註冊流程

如果需要註冊,肯定需要一個註冊的實例端

在EurekaClientAutoConfiguration中尋找EurekaClient

@Bean(destroyMethod = "shutdown")
        // @ConditionalOnMissingBean如果spring中沒有該bean則創建,反之不創建
		@ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT)
		public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config) {
			return new CloudEurekaClient(manager, config, this.optionalArgs,
					this.context);
		}

點進去可以看到它是一個接口

public interface EurekaClient extends LookupService

查看它的實現類DiscoveryClient,先是進行一堆初始化賦值,然後創建了三個線程池,最後初始化了所有定時任務

@Inject
    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                    Provider<BackupRegistry> backupRegistryProvider) {
        // .. 一些的初始化賦值

        try {
            // default size of 2 - 1 each for heartbeat and cacheRefresh
            // 定時任務
            scheduler = Executors.newScheduledThreadPool(2,
                    new ThreadFactoryBuilder()
                            .setNameFormat("DiscoveryClient-%d")
                            .setDaemon(true)
                            .build());
            // 心跳檢測
            heartbeatExecutor = new ThreadPoolExecutor(
                    1, clientConfig.getHeartbeatExecutorThreadPoolSize(), 0, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>(),
                    new ThreadFactoryBuilder()
                            .setNameFormat("DiscoveryClient-HeartbeatExecutor-%d")
                            .setDaemon(true)
                            .build()
            );  // use direct handoff
            
            // 緩存刷新
            cacheRefreshExecutor = new ThreadPoolExecutor(
                    1, clientConfig.getCacheRefreshExecutorThreadPoolSize(), 0, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>(),
                    new ThreadFactoryBuilder()
                            .setNameFormat("DiscoveryClient-CacheRefreshExecutor-%d")
                            .setDaemon(true)
                            .build()
            );  // use direct handoff

            // ...
        } catch (Throwable e) {
            throw new RuntimeException("Failed to initialize DiscoveryClient!", e);
        }

        //...
        // 初始化了所有定時任務
        initScheduledTasks();

        //...
    }

繼續追蹤initScheduledTasks()方法,看看心跳檢測初始化時都幹了些什麼

/**
     * Initializes all scheduled tasks.
     */
    private void initScheduledTasks() {

            // ...

            // Heartbeat timer
            scheduler.schedule(
                    new TimedSupervisorTask(
                            "heartbeat",
                            scheduler,
                            heartbeatExecutor,
                            renewalIntervalInSecs,
                            TimeUnit.SECONDS,
                            expBackOffBound,
                            new HeartbeatThread()
                    ),
                    renewalIntervalInSecs, TimeUnit.SECONDS);
                    
            // ...
    }

調用了renew()方法,繼續跟蹤看看它做了什麼

/**
     * The heartbeat task that renews the lease in the given intervals.
     */
    private class HeartbeatThread implements Runnable {

        public void run() {
            if (renew()) {
                lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
            }
        }
    }

InstanceInfo顧名思義,實例信息,先是創建一個實例集合,請求一次服務,如果該服務狀態值是404,則計數器+1並調用註冊方法

/**
     * Renew with the eureka service by making the appropriate REST call
     */
    boolean renew() {
        // 定義一個實例信息集合 
        EurekaHttpResponse<InstanceInfo> httpResponse;
        try {
            // 請求服務
            httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
            logger.debug("{} - Heartbeat status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode());
            if (httpResponse.getStatusCode() == 404) {
                // 如果沒有註冊過,則計數器+1
                REREGISTER_COUNTER.increment();
                logger.info("{} - Re-registering apps/{}", PREFIX + appPathIdentifier, instanceInfo.getAppName());
                // 調用註冊方法
                return register();
            }
            return httpResponse.getStatusCode() == 200;
        } catch (Throwable e) {
            logger.error("{} - was unable to send heartbeat!", PREFIX + appPathIdentifier, e);
            return false;
        }
    }

繼續追蹤register()方法

將實例信息放入了集合中,通過適當的REST調用向eureka進行服務註冊,返回是否成功

/**
     * Register with the eureka service by making the appropriate REST call.
     */
    boolean register() throws Throwable {
        logger.info(PREFIX + appPathIdentifier + ": registering service...");
        // 定義一個集合
        EurekaHttpResponse<Void> httpResponse;
        try {
            // 向eureka服務註冊
            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;
    }

總結

EurekaClient的實現類DiscoveryClient中,DiscoveryClient方法初始化了三個線程池,定時任務的,心跳的,緩存的.

在初始化心時任務中,初始化了心跳檢測的線程,並創建了HeartbeatThread執行了renew()更新方法

通過該方法,請求Eureka服務,如果返回404,則計數器+1,再通過REST調用向eureka服務註冊並返回是否註冊成功.如果不是404,則返回請求是否成功的狀態值.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章