SpringCloud系列——EurekaClient注册表更新机制

Eureka注册表整体框架图:SpringCloud系列——EurekaClient注册表更新机制_第1张图片

Eureka客户端更新机制图解

还是直接看图来得实在:
SpringCloud系列——EurekaClient注册表更新机制_第2张图片
这个注册表中含有所有服务的信息,比如服务的IP,端口,实例状态等,在这个商城项目中,用户在浏览商品之后,想买此商品,这时商品服务会去调用订单服务,而获取订单服务的IP和端口就是由Eureka注册中心中的注册表维护着的。

DiscoveryClient类解析

DiscoveryClientEureka客户端向Erueka服务端获取注册表/注册/发送心跳的具体实现类,可以说是我们跟Eureka客户端打交道最多的一个类了。
Eureka服务端一般都是公司基础架构部门或者架构师维护,而我们平时使用springcloud全家桶来进行开发的话,都是使用的Eureka客户端,只要依赖如下即可:

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>

关于Eureka客户端注册表的相关信息,也是围绕DiscoveryClient来讲解的。

首次获取全量注册表

DiscoverClient的构造方法中就实现了:

DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                    Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
     
	......
	boolean primaryFetchRegistryResult = fetchRegistry(false);
	......
}
// fetchRegistry()最终会调用getAndStoreFullRegistry()
private void getAndStoreFullRegistry(){
     
	...
	Applications apps = null;
    EurekaHttpResponse<Applications> httpResponse = clientConfig.getRegistryRefreshSingleVipAddress() == null
            ? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get())
            : eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());
    if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
     
        apps = httpResponse.getEntity();
    }
   .......
}

定时拉取增量注册表以及hashcode比对

建立定时任务:

 cacheRefreshTask = new TimedSupervisorTask(
                    "cacheRefresh",
                    scheduler,
                    cacheRefreshExecutor,
                    registryFetchIntervalSeconds,
                    TimeUnit.SECONDS,
                    expBackOffBound,
                    new CacheRefreshThread()
            );
 scheduler.schedule(cacheRefreshTask, registryFetchIntervalSeconds, TimeUnit.SECONDS);

定时任务最终会走到拉取注册表的方法:

private boolean fetchRegistry(boolean forceFullRegistryFetch) {
     
    Applications applications = getApplications();
    //clientConfig.shouldDisableDelta()默认是false
	if (clientConfig.shouldDisableDelta() || forceFullRegistryFetch){
     
		getAndStoreFullRegistry();
	}else{
     
		getAndUpdateDelta(applications);
	}
	applications.setAppsHashCode(applications.getReconcileHashCode());
}

private void getAndUpdateDelta(Applications applications) throws Throwable {
     
	......
	//如果从eureka服务端获取的hashcode,和增量注册表+本地注册表合并后的hashcode不一致的话,就得重新拉取全量注册表
	if (!reconcileHashCode.equals(delta.getAppsHashCode()) || clientConfig.shouldLogDeltaDiff()) {
     
         reconcileAndLogDifference(delta, reconcileHashCode);  
    }
    ......
}

private void reconcileAndLogDifference(Applications delta, String reconcileHashCode) throws Throwable {
     
	......
	EurekaHttpResponse<Applications> httpResponse = clientConfig.getRegistryRefreshSingleVipAddress() == null
                ? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get())
                : eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());
    Applications serverApps = httpResponse.getEntity();
	......
}

这里有关键的两个配置参数:

# 表示每隔多长,去拉取一次注册表
eureka.client.registry-fetch-interval-seconds=30
# 默认是false,如果设置为true,则之后每次拉取的注册表,都是全量注册表,而不是增量的了,个人觉得,如果是eureka客户端应用实例机器配置以及内存配置还不错的话,可以设置为true,否则还是用默认的吧
eureka.client.disable-delta=false

租期续约和发送心跳概念解释

最开始我使用Eureka时,经常被这两个概念绕晕,但在DiscoverClient类中得到了答案:

 private class HeartbeatThread implements Runnable {
     
    public void run() {
     
        if (renew()) {
     
            lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
        }
    }
}

特么应用实例发送心跳,其实就是续约啊!!!

你可能感兴趣的:(SpringCloud,eureka,注册表)