关于eureka:Eureka-Client服务启动

7次阅读

共计 5886 个字符,预计需要花费 15 分钟才能阅读完成。

咱们从上面的图能够看出,作为一个 client 端,他有以下性能:

  • Register(服务注册):向 Eureka Server 注册本身的信息,比方 IP 地址、端口等。
  • Renew(服务续约):服务启动后,每隔 30 秒会向 Eureka Server 发送心跳进行服务续约。
  • Get(服务发现):获取向 Eureka Server 注册的服务列表,并缓存本地,默认 30 秒。
  • Cancel(服务下线):向 Eureka Server 发送下线信息,Eureka Server 会把这个服务标记为下线。

服务启动

springboot 的主动拆卸读取 Eureka Client 的 spring.factories 文件,咱们看到他外面有多个 EnableAutoConfiguration,次要的类是 EurekaClientAutoConfiguration。EurekaClientAutoConfiguration 类中有多个 bean 的加载,咱们先看看 EurekaInstanceConfigBean 的加载。

EurekaInstanceConfigBean

EurekaInstanceConfigBean 有个 @ConfigurationProperties(“eureka.instance”) 注解,所以咱们在配置文件里写的 eureka.instance.instanceId 这类的信息最终都在赋值给这个类。还有比拟重要的 leaseRenewalIntervalInSeconds 续约频率(默认每 30 秒)、leaseExpirationDurationInSeconds 续约过期工夫(默认 90 秒)都是在这个类配置的。

@Bean
@ConditionalOnMissingBean(value = EurekaInstanceConfig.class,
        search = SearchStrategy.CURRENT)
public EurekaInstanceConfigBean eurekaInstanceConfigBean(InetUtils inetUtils,
        ManagementMetadataProvider managementMetadataProvider) {
    // 省略局部代码
    EurekaInstanceConfigBean instance = new EurekaInstanceConfigBean(inetUtils);
    // 省略局部代码
    return instance;
}

ApplicationInfoManager

ApplicationInfoManager 也是在 EurekaClientAutoConfiguration 类中。
创立 eurekaApplicationInfoManager 对象的时候,会先创立 InstanceInfo 对象,InstanceInfo 对象的值大部分是从 EurekaInstanceConfig 复制过去的,另外租约信息是寄存在 InstanceInfo 的 leaseInfo 中。
所以初始化 ApplicationInfoManager 的时候,就是赋值 EurekaInstanceConfig 和 InstanceInfo。

@Bean
@ConditionalOnMissingBean(value = ApplicationInfoManager.class,
        search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public ApplicationInfoManager eurekaApplicationInfoManager(EurekaInstanceConfig config) {InstanceInfo instanceInfo = new InstanceInfoFactory().create(config);
    return new ApplicationInfoManager(config, instanceInfo);
}

EurekaClientConfigBean

EurekaClientConfigBean 也是一个配置信息的 bean,他次要是 EurekaClient 和 EurekaServer 相干的信息,比方 EurekaServer 的地址 defaultZone、是否从注册核心拉取注册信息 fetchRegistry(默认 true),拉取的频率 registryFetchIntervalSeconds(默认每 30 秒)、是否向注册核心注册 registerWithEureka(默认 true)等。

@Bean
@ConditionalOnMissingBean(value = EurekaClientConfig.class,
        search = SearchStrategy.CURRENT)
public EurekaClientConfigBean eurekaClientConfigBean(ConfigurableEnvironment env) {return new EurekaClientConfigBean();
}

EurekaClient

创立一个 EurekaClient 类,这个类就是负责服务的注册、续约、勾销、获取注册列表。

@Bean(destroyMethod = "shutdown")
@ConditionalOnMissingBean(value = EurekaClient.class,
        search = SearchStrategy.CURRENT)
@org.springframework.cloud.context.config.annotation.RefreshScope
@Lazy
public EurekaClient eurekaClient(ApplicationInfoManager manager,
        EurekaClientConfig config, EurekaInstanceConfig instance,
        @Autowired(required = false) HealthCheckHandler healthCheckHandler) {
    ApplicationInfoManager appManager;
    if (AopUtils.isAopProxy(manager)) {appManager = ProxyUtils.getTargetObject(manager);
    }
    else {appManager = manager;}
    CloudEurekaClient cloudEurekaClient = new CloudEurekaClient(appManager,
            config, this.optionalArgs, this.context);
    cloudEurekaClient.registerHealthCheck(healthCheckHandler);
    return cloudEurekaClient;
}

联合下面几个类的加载以及 EurekaClient 的加载,咱们能够晓得这几个类的关系如下:

在 DiscoveryClient 的构造函数里,次要是初始化一些配置参数,以及为拉取注册表信息、初始化定时工作。

@Inject
DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
        Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
    // 初始化 applicationInfoManager、config 等略

    try {
        // 创立外围数为 2 的线程池,一个用于 heartbeat,一个用于 cacheRefresh
        // 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
        // 与 EurekaServer 网络通信用的
        eurekaTransport = new EurekaTransport();
        scheduleServerEndpointTask(eurekaTransport, args);
        // 其余的略
        
    } catch (Throwable e) {throw new RuntimeException("Failed to initialize DiscoveryClient!", e);
    }
    
    if (clientConfig.shouldFetchRegistry()) {
        try {
            // 拉取注册表信息
            boolean primaryFetchRegistryResult = fetchRegistry(false);
            // 其余的略,没有拉取胜利从备份注册核心获取
        }
    }
    // 其余的略
    // 初始化定时工作
    initScheduledTasks();
    // 其余的略
}

initScheduledTasks,用来开启更新服务注册列表和续租的定时工作,以及对 EurekaServer 的注册。

private void initScheduledTasks() {if (clientConfig.shouldFetchRegistry()) {
        // registry cache refresh timer
        // 这个定时工作是更新服务注册列表
        // 更新频率
        int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
        // 提早最大乘数,比方更新频率是 5s,那最大延迟时间就是 50s,这个前面讲线程的时候会具体说
        int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
        cacheRefreshTask = new TimedSupervisorTask(
                "cacheRefresh",
                scheduler,
                cacheRefreshExecutor,
                registryFetchIntervalSeconds,
                TimeUnit.SECONDS,
                expBackOffBound,
                new CacheRefreshThread());
        scheduler.schedule(
                cacheRefreshTask,
                registryFetchIntervalSeconds, TimeUnit.SECONDS);
    }
    instanceInfoReplicator = new InstanceInfoReplicator(
        this,
        instanceInfo,
        clientConfig.getInstanceInfoReplicationIntervalSeconds(),
        2);
    if (clientConfig.shouldRegisterWithEureka()) {
        // 这个定时工作是续租
        // 续约频率
        int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
        int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound();
        logger.info("Starting heartbeat executor:" + "renew interval is: {}", renewalIntervalInSecs);

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

        // 其余的略
        // 注册到注册核心
        instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
    } else {logger.info("Not registering with Eureka server per configuration");
    }
}

好了,以上对 EurekaServer 的注册、续租、注册表获取都提及到了,前面再具体的解说这些内容。

正文完
 0