咱们从上面的图能够看出,作为一个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@Lazypublic 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@Lazypublic 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的构造函数里,次要是初始化一些配置参数,以及为拉取注册表信息、初始化定时工作。

@InjectDiscoveryClient(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的注册、续租、注册表获取都提及到了,前面再具体的解说这些内容。