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,则返回请求是否成功的状态值.

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