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

tech2022-09-19  57

Eureka注册表整体框架图:

Eureka客户端更新机制图解

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

DiscoveryClient类解析

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

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </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(); } } }

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

最新回复(0)