Eureka客户端源码分析

本文解析了Spring Cloud Netflix Eureka Client中的EurekaClientAutoConfiguration关键配置,深入剖析了心跳续约(Heartbeat)和定期从Eureka Server拉取服务列表(Registry Fetch)的实现细节,包括定时任务、状态变更监听和实例信息复制等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

spring-cloud-netflix-eureka-client/2.2.9.RELEASE/spring-cloud-netflix-eureka-client-2.2.9.RELEASE-sources.jar!/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\
org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration,\
//看到这里
org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\
org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\
org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.reactive.EurekaReactiveDiscoveryClientConfiguration,\
org.springframework.cloud.netflix.eureka.loadbalancer.LoadBalancerEurekaAutoConfiguration

org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.netflix.eureka.config.EurekaConfigServerBootstrapConfiguration

EurekaClientAutoConfiguration

@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties
@ConditionalOnClass(EurekaClientConfig.class)
@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)
@ConditionalOnDiscoveryEnabled
@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class,
		CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })
@AutoConfigureAfter(name = {
		"org.springframework.cloud.netflix.eureka.config.DiscoveryClientOptionalArgsConfiguration",
		"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration",
		"org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration",
		"org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration" })
public class EurekaClientAutoConfiguration {
	
	//省略其他源码

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingRefreshScope
    protected static class EurekaClientConfiguration {
		@Bean(destroyMethod = "shutdown")
		@ConditionalOnMissingBean(value = EurekaClient.class,
				search = SearchStrategy.CURRENT)
		public EurekaClient eurekaClient(ApplicationInfoManager manager,
				EurekaClientConfig config) {
			//创建了CloudEurekaClient
			return new CloudEurekaClient(manager, config, this.optionalArgs,
					this.context);
		}
    }
}

CloudEurekaClient的父类DiscoveryClient的构造函数

    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args,
                    Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
         //省略部分代码
        initScheduledTasks();                
    }
 	private void initScheduledTasks() {
 		//fetchRegistry默认为true
        if (clientConfig.shouldFetchRegistry()) {
        	//registryFetchIntervalSeconds 默认30秒 ,从eureka服务端拉取服务列表
            int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds();
            int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
            cacheRefreshTask = new TimedSupervisorTask(
                    "cacheRefresh",
                    scheduler,
                    cacheRefreshExecutor,
                    registryFetchIntervalSeconds,
                    TimeUnit.SECONDS,
                    expBackOffBound,
                    new CacheRefreshThread()
            );
            scheduler.schedule(
                    cacheRefreshTask,
                    registryFetchIntervalSeconds, TimeUnit.SECONDS);
        }
		//registerWithEureka默认为true
        if (clientConfig.shouldRegisterWithEureka()) {
        	//renewalIntervalInSecs默认为30s,心跳续约间隔
            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);

            // InstanceInfo replicator
            instanceInfoReplicator = new InstanceInfoReplicator(
                    this,
                    instanceInfo,
                    clientConfig.getInstanceInfoReplicationIntervalSeconds(),
                    2); // burstSize
			
			//创建状态改变监听器,监听实例状态改变,立即向服务端汇报
            statusChangeListener = new ApplicationInfoManager.StatusChangeListener() {
                @Override
                public String getId() {
                    return "statusChangeListener";
                }
				
                @Override
                public void notify(StatusChangeEvent statusChangeEvent) {
                    logger.info("Saw local status change event {}", statusChangeEvent);
                    instanceInfoReplicator.onDemandUpdate();
                }
            };

            if (clientConfig.shouldOnDemandUpdateStatusChange()) {
            	//注册状态改变监听器,就是放到listeners中
                applicationInfoManager.registerStatusChangeListener(statusChangeListener);
            }
			//定时把实例状态状态向服务端汇报
			//将isInstanceInfoDirty修改为true
            instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
        } else {
            logger.info("Not registering with Eureka server per configuration");
        }
    }
	
	class CacheRefreshThread implements Runnable {
        public void run() {
        	//从注册中心拉取服务列表
            refreshRegistry();
        }
    }

    @VisibleForTesting
    void refreshRegistry() {
        try {
            //省略部分代码

            boolean success = fetchRegistry(remoteRegionsModified);
            if (success) {
            	//更新服务列表的个数
                registrySize = localRegionApps.get().size();
                //更新最近一次拉取服务列表的时间
                lastSuccessfulRegistryFetchTimestamp = System.currentTimeMillis();
            }
			
			//省略部分代码
           
        } catch (Throwable e) {
            logger.error("Cannot fetch registry from server", e);
        }
    }
    private boolean fetchRegistry(boolean forceFullRegistryFetch) {
        Stopwatch tracer = FETCH_REGISTRY_TIMER.start();

        try {
            //从localRegionApps(客户端本地缓存的服务列表信息) 获取 服务应用
            Applications applications = getApplications();
			
			//是否禁用增量拉取,默认false
            if (clientConfig.shouldDisableDelta()
            		//eureka服务端地址不为空
                    || (!Strings.isNullOrEmpty(clientConfig.getRegistryRefreshSingleVipAddress()))
                    //入参forceFullRegistryFetch可以传入true,强制进行全量拉取
                    || forceFullRegistryFetch
                    //本地服务列表为空
                    || (applications == null)  
                    || (applications.getRegisteredApplications().size() == 0)
                    || (applications.getVersion() == -1)) //Client application does not have latest library supporting delta
            {
                logger.info("Disable delta property : {}", clientConfig.shouldDisableDelta());
                logger.info("Single vip registry refresh property : {}", clientConfig.getRegistryRefreshSingleVipAddress());
                logger.info("Force full registry fetch : {}", forceFullRegistryFetch);
                logger.info("Application is null : {}", (applications == null));
                logger.info("Registered Applications size is zero : {}",
                        (applications.getRegisteredApplications().size() == 0));
                logger.info("Application version is -1: {}", (applications.getVersion() == -1));
               	//全量拉取
                getAndStoreFullRegistry();
            } 
            //增量拉取
            else {
                getAndUpdateDelta(applications);
            } 
            //设置服务列表计算出的hashcode
            applications.setAppsHashCode(applications.getReconcileHashCode());
            logTotalInstances();
        } catch (Throwable e) {
            logger.info(PREFIX + "{} - was unable to refresh its cache! This periodic background refresh will be retried in {} seconds. status = {} stacktrace = {}",
                    appPathIdentifier, clientConfig.getRegistryFetchIntervalSeconds(), e.getMessage(), ExceptionUtils.getStackTrace(e));
            return false;
        } finally {
            if (tracer != null) {
                tracer.stop();
            }
        }
		//发布CacheRefreshedEvent事件 和 HeartbeatEvent事件(子类CloudEurekaClient发布)
        onCacheRefreshed();

        //发布StatusChangeEvent事件
        updateInstanceRemoteStatus();

        // registry was fetched successfully, so return true
        return true;
    }
    private void getAndStoreFullRegistry() throws Throwable {
    	//获取上一次拉去服务列表的generation
        long currentUpdateGeneration = fetchRegistryGeneration.get();

        logger.info("Getting all instance registry info from the eureka server");

        Applications apps = null;
        EurekaHttpResponse<Applications> httpResponse = clientConfig.getRegistryRefreshSingleVipAddress() == null
        		//远程调用,从eureka服务端拉去服务列表。 
                //这里的eurekaTransport.queryClient被多个不同功能的类包装,着重来看RetryableEurekaHttpClient 
                ? eurekaTransport.queryClient.getApplications(remoteRegionsRef.get()) 
                : eurekaTransport.queryClient.getVip(clientConfig.getRegistryRefreshSingleVipAddress(), remoteRegionsRef.get());
        if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
            apps = httpResponse.getEntity();
        }
        logger.info("The response status is {}", httpResponse.getStatusCode());

        if (apps == null) {
            logger.error("The application is null for some reason. Not storing this information");
        } 
        //cas更新currentUpdateGeneration + 1
        else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {			
        	//全量更新本地服务列表缓存
            localRegionApps.set(this.filterAndShuffle(apps));
            logger.debug("Got full registry with apps hashcode {}", apps.getAppsHashCode());
        } else {
            logger.warn("Not updating applications as another thread is updating it already");
        }
    }
    private void getAndUpdateDelta(Applications applications) throws Throwable {
   	    //获取上一次拉去服务列表的generation
        long currentUpdateGeneration = fetchRegistryGeneration.get();

        Applications delta = null;
        //从eureka服务端增量获取服务列表。 
        EurekaHttpResponse<Applications> httpResponse = eurekaTransport.queryClient.getDelta(remoteRegionsRef.get());
        if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
            delta = httpResponse.getEntity();
        }

        if (delta == null) {
            logger.warn("The server does not allow the delta revision to be applied because it is not safe. "
                    + "Hence got the full registry.");
            //增量拉取未获取到数据,重新全量拉取
            getAndStoreFullRegistry();
        } 
        //cas更新currentUpdateGeneration + 1
        else if (fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1)) {
            logger.debug("Got delta update with apps hashcode {}", delta.getAppsHashCode());
            String reconcileHashCode = "";
            //加锁
            if (fetchRegistryUpdateLock.tryLock()) {
                try {
                	//增量更新本地服务列表缓存
                    updateDelta(delta);
                    //计算更新后的所有服务列表的hashCode
                    reconcileHashCode = getReconcileHashCode(applications);
                } finally {
                    fetchRegistryUpdateLock.unlock();
                }
            } else {
                logger.warn("Cannot acquire update lock, aborting getAndUpdateDelta");
            }
            // There is a diff in number of instances for some reason
            //判断更新后的hashCode , 和eureka服务端回传的的hashCode 是否一致
            if (!reconcileHashCode.equals(delta.getAppsHashCode()) || clientConfig.shouldLogDeltaDiff()) {
            	//不一致, 则 重新全量拉取服务列表更新本地缓存
                reconcileAndLogDifference(delta, reconcileHashCode);  // this makes a remoteCall
            }
        }
        else {
            logger.warn("Not updating application delta as another thread is updating it already");
            logger.debug("Ignoring delta update with apps hashcode {}, as another thread is updating it already", delta.getAppsHashCode());
        }
    }
    private void updateDelta(Applications delta) {
        int deltaCount = 0;
        //循环所有的增量拉取的服务列表
        for (Application app : delta.getRegisteredApplications()) {
        	//循环服务下的所有实例
            for (InstanceInfo instance : app.getInstances()) {
            	//从 localRegionApps本地缓存 获取到所有服务applications 
                Applications applications = getApplications();
                String instanceRegion = instanceRegionChecker.getInstanceRegion(instance);
                if (!instanceRegionChecker.isLocalRegion(instanceRegion)) {
                    Applications remoteApps = remoteRegionVsApps.get(instanceRegion);
                    if (null == remoteApps) {
                        remoteApps = new Applications();
                        remoteRegionVsApps.put(instanceRegion, remoteApps);
                    }
                    applications = remoteApps;
                }

                ++deltaCount;
                //如果是新增的服务实例
                if (ActionType.ADDED.equals(instance.getActionType())) {
                	//从 applications 使用服务名称获取到服务
                    Application existingApp = applications.getRegisteredApplications(instance.getAppName());
                    if (existingApp == null) {
                    	//获取不到,则添加
                        applications.addApplication(app);
                    }
                    logger.debug("Added instance {} to the existing apps in region {}", instance.getId(), instanceRegion);
                    //将服务实例添加到服务列表中
                    applications.getRegisteredApplications(instance.getAppName()).addInstance(instance);
                } 
                //修改的服务实例
                else if (ActionType.MODIFIED.equals(instance.getActionType())) {
                	//和新增一样的操作
                    Application existingApp = applications.getRegisteredApplications(instance.getAppName());
                    if (existingApp == null) {
                        applications.addApplication(app);
                    }
                    logger.debug("Modified instance {} to the existing apps ", instance.getId());

                    applications.getRegisteredApplications(instance.getAppName()).addInstance(instance);

                } 
                //删除的服务实例
                else if (ActionType.DELETED.equals(instance.getActionType())) {
               		//从 applications 使用服务名称获取到服务
                    Application existingApp = applications.getRegisteredApplications(instance.getAppName());
                    if (existingApp != null) {
                        logger.debug("Deleted instance {} to the existing apps ", instance.getId());
                        //从该服务中移除该服务实例
                        existingApp.removeInstance(instance);
                        /*
                         * We find all instance list from application(The status of instance status is not only the status is UP but also other status)
                         * if instance list is empty, we remove the application.
                         */
                        //获取对应的服务的所有服务实例,如果为空,则移除该服务
                        if (existingApp.getInstancesAsIsFromEureka().isEmpty()) {
                            applications.removeApplication(existingApp);
                        }
                    }
                }
            }
        }
        logger.debug("The total number of instances fetched by the delta processor : {}", deltaCount);

        getApplications().setVersion(delta.getVersion());
        getApplications().shuffleInstances(clientConfig.shouldFilterOnlyUpInstances());

        for (Applications applications : remoteRegionVsApps.values()) {
            applications.setVersion(delta.getVersion());
            applications.shuffleInstances(clientConfig.shouldFilterOnlyUpInstances());
        }
    }
    private class HeartbeatThread implements Runnable {

        public void run() {
        	//心跳续约
            if (renew()) {
            	//更新最后最后一次心跳续约的时间
                lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
            }
        }
    }
    boolean renew() {
        EurekaHttpResponse<InstanceInfo> httpResponse;
        try {
        	//远程调用,发送心跳续约请求
            httpResponse = eurekaTransport.registrationClient.sendHeartBeat(instanceInfo.getAppName(), instanceInfo.getId(), instanceInfo, null);
            logger.debug(PREFIX + "{} - Heartbeat status: {}", appPathIdentifier, httpResponse.getStatusCode());
            //如果心跳续约请求的服务实例不存在,
            if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
                REREGISTER_COUNTER.increment();
                logger.info(PREFIX + "{} - Re-registering apps/{}", appPathIdentifier, instanceInfo.getAppName());
                long timestamp = instanceInfo.setIsDirtyWithTime();
                //发送服务实例注册请求
                boolean success = register();
                if (success) {
                    instanceInfo.unsetIsDirty(timestamp);
                }
                return success;
            }
            return httpResponse.getStatusCode() == Status.OK.getStatusCode();
        } catch (Throwable e) {
            logger.error(PREFIX + "{} - was unable to send heartbeat!", appPathIdentifier, e);
            return false;
        }
    }
     boolean register() throws Throwable {
        logger.info(PREFIX + "{}: registering service...", appPathIdentifier);
        EurekaHttpResponse<Void> httpResponse;
        try {
        	//发送服务实例注册请求
        	//registrationClient一样被RetryableEurekaHttpClient所包装
            httpResponse = eurekaTransport.registrationClient.register(instanceInfo);
        } catch (Exception e) {
            logger.warn(PREFIX + "{} - registration failed {}", appPathIdentifier, e.getMessage(), e);
            throw e;
        }
        if (logger.isInfoEnabled()) {
            logger.info(PREFIX + "{} - registration status: {}", appPathIdentifier, httpResponse.getStatusCode());
        }
        return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
    }

RetryableEurekaHttpClient

	@Override
    protected <R> EurekaHttpResponse<R> execute(RequestExecutor<R> requestExecutor) {
        List<EurekaEndpoint> candidateHosts = null;
        int endpointIdx = 0;
        //写死了 numberOfRetries 为 3次
        for (int retry = 0; retry < numberOfRetries; retry++) {
        	//持有了currentHttpClient 
            EurekaHttpClient currentHttpClient = delegate.get();
            EurekaEndpoint currentEndpoint = null;
            //如果currentHttpClient 为空
            if (currentHttpClient == null) {
                if (candidateHosts == null) {
                	//获取配置的所有eureka服务端实例
                    candidateHosts = getHostCandidates();
                    if (candidateHosts.isEmpty()) {
                        throw new TransportException("There is no known eureka server; cluster server list is empty");
                    }
                }
                if (endpointIdx >= candidateHosts.size()) {
                    throw new TransportException("Cannot execute request on any known server");
                }
				//endpointIdx加一,每次循环重试 获取到不同的eureka服务端
                currentEndpoint = candidateHosts.get(endpointIdx++);
                //设置为currentHttpClient 
                currentHttpClient = clientFactory.newClient(currentEndpoint);
            }

            try {
            	//currentHttpClient交给下一个包装类去完成调用
                EurekaHttpResponse<R> response = requestExecutor.execute(currentHttpClient);
                //eureka服务端相应的状态码 为 客户端可以接受的状态码 ,则说明调用正常返回。直接返回响应结果
                if (serverStatusEvaluator.accept(response.getStatusCode(), requestExecutor.getRequestType())) {
                    delegate.set(currentHttpClient);
                    if (retry > 0) {
                        logger.info("Request execution succeeded on retry #{}", retry);
                    }
                    return response;
                }
                //不是服务端正常返回的状态码 。 需要重试,进行下次循环
                logger.warn("Request execution failure with status code {}; retrying on another server if available", response.getStatusCode());
            } catch (Exception e) {
            	//发生异常,需要重试
                logger.warn("Request execution failed with message: {}", e.getMessage());  // just log message as the underlying client should log the stacktrace
            }

            // Connection error or 5xx from the server that must be retried on another server
            //将currentHttpClient设置为空。切换到其他eureka节点去调用
            delegate.compareAndSet(currentHttpClient, null);
            if (currentEndpoint != null) {
                quarantineSet.add(currentEndpoint);
            }
        }
        throw new TransportException("Retry limit reached; giving up on completing the request");
    }
    void refreshInstanceInfo() {
        applicationInfoManager.refreshDataCenterInfoIfRequired();
        //刷新本地lease信息
        applicationInfoManager.refreshLeaseInfoIfRequired();

        InstanceStatus status;
        try {
        	//获取健康检查实现类
        	//可以实现HealthCheckHandler接口,作为bean注入到容器中。没有的话,默认实例化一个HealthCheckCallbackToHandlerBridge(过时了,支持HealthCheckCallback接口)
        	//EurekaClient会依赖注入HealthCheckHandler类型的bean。
            status = getHealthCheckHandler().getStatus(instanceInfo.getStatus());
        } catch (Exception e) {
            logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", e);
            status = InstanceStatus.DOWN;
        }
		
		//通知状态改变监听器
        if (null != status) {
            applicationInfoManager.setInstanceStatus(status);
        }
    }

InstanceInfoReplicator

class InstanceInfoReplicator implements Runnable {

	public void start(int initialDelayMs) {
        if (started.compareAndSet(false, true)) {
        	//修改isInstanceInfoDirty为true , 初始发送客户端注册请求
            instanceInfo.setIsDirty();  // for initial register
            //延迟initialDelayMs,执行一次
            Future next = scheduler.schedule(this, initialDelayMs, TimeUnit.SECONDS);
            //设置Future 到 scheduledPeriodicRef
            scheduledPeriodicRef.set(next);
        }
    }
	
	public void run() {
        try {
        	//刷新本地lease信息
            discoveryClient.refreshInstanceInfo();
			
			//如果isInstanceInfoDirty为true , 返回lastDirtyTimestamp
			//否则,返回null
            Long dirtyTimestamp = instanceInfo.isDirtyWithTime();
            if (dirtyTimestamp != null) {
            	//发送实例注册请求 。
            	//如果 服务端 的 客户端实例 不存在,则完成实例注册 
            	//如果 服务端 的 客户端实例 存在, 则更新实例的状态
                discoveryClient.register();
                //设置isInstanceInfoDirty为false
                instanceInfo.unsetIsDirty(dirtyTimestamp);
            }
        } catch (Throwable t) {
            logger.warn("There was a problem with the instance info replicator", t);
        } finally {
        	//设置下一次执行
            Future next = scheduler.schedule(this, replicationIntervalSeconds, TimeUnit.SECONDS);
            //Future 设置到 scheduledPeriodicRef中
            scheduledPeriodicRef.set(next);
        }
    }
	
	public boolean onDemandUpdate() {
        if (rateLimiter.acquire(burstSize, allowedRatePerMinute)) {
            if (!scheduler.isShutdown()) {
            	//立即执行
                scheduler.submit(new Runnable() {
                    @Override
                    public void run() {
                        logger.debug("Executing on-demand update of local InstanceInfo");
    					//获取下一次准备执行的任务的future
                        Future latestPeriodic = scheduledPeriodicRef.get();
                        //如果还没有执行,则取消该任务
                        if (latestPeriodic != null && !latestPeriodic.isDone()) {
                            logger.debug("Canceling the latest scheduled update, it will be rescheduled at the end of on demand update");
                            latestPeriodic.cancel(false);
                        }
    					//调用run方法,发送注册请求以更新客户端状态
                        InstanceInfoReplicator.this.run();
                    }
                });
                return true;
            } else {
                logger.warn("Ignoring onDemand update due to stopped scheduler");
                return false;
            }
        } else {
            logger.warn("Ignoring onDemand update due to rate limiter");
            return false;
        }
    }
}

ApplicationInfoManager

	public void refreshLeaseInfoIfRequired() {
		//获取lease
        LeaseInfo leaseInfo = instanceInfo.getLeaseInfo();
        if (leaseInfo == null) {
            return;
        }
        //实例过期时间间隔
        int currentLeaseDuration = config.getLeaseExpirationDurationInSeconds();
        //心跳续约间隔
        int currentLeaseRenewal = config.getLeaseRenewalIntervalInSeconds();
        //判断lease的 过期时间间隔 心跳续约间隔 是否和 配置的一致, 不一致,则创建新的lease ,设置到instanceInfo中
        if (leaseInfo.getDurationInSecs() != currentLeaseDuration || leaseInfo.getRenewalIntervalInSecs() != currentLeaseRenewal) {
            LeaseInfo newLeaseInfo = LeaseInfo.Builder.newBuilder()
                    .setRenewalIntervalInSecs(currentLeaseRenewal)
                    .setDurationInSecs(currentLeaseDuration)
                    .build();
            instanceInfo.setLeaseInfo(newLeaseInfo);
            instanceInfo.setIsDirty();
        }
    }
	public synchronized void setInstanceStatus(InstanceStatus status) {
		//更新后的状态
	    InstanceStatus next = instanceStatusMapper.map(status);
        if (next == null) {
            return;
        }
		//更新前的状态
        InstanceStatus prev = instanceInfo.setStatus(next);
        if (prev != null) {
        	//遍历listeners,调用notify方法
            for (listener : listeners.values()) {
                try {
                    listener.notify(new StatusChangeEvent(prev, next));
                } catch (Exception e) {
                    logger.warn("failed to notify listener: {}", listener.getId(), e);
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值