Eureka Client 加载过程以及源码

摘要:
Eureka体系结构图角色分析服务提供商是一个Eureka客户端,它向EurekaServer注册并更新自己的信息。同时,可以从Eureka Server注册表获取有关其他服务的信息。服务注册表提供服务注册和发现功能。每个EurekaCient都向EurekaServer注册自己的信息。它还可以通过EurekaServer获取有关其他服务的信息,以发现和调用其他服务。服务消费者是Eureka客户

Eureka架构图

Eureka Client 加载过程以及源码第1张

Eureka Client 加载过程以及源码第2张

角色分析

服务提供者

是一个eureka client,向Eureka Server注册和更新自己的信息,同时能从Eureka Server注册表中获取到其他服务的信息

服务注册中心

  • 提供服务注册和发现的功能
  • 每个Eureka Cient向Eureka Server注册自己的信息
  • 也可以通过Eureka Server获取到其他服务的信息达到发现和调用其他服务的目的

服务消费者

  • 是一个eureka client
  • 通过Eureka Server获取注册到其上其他服务的信息
  • 从而根据信息找到所需的服务发起远程调用

同步复制

  • Eureka Server之间注册表信息的同步复制
  • 使Eureka Server集群中不同注册表中服务实例信息保持一致

远程调用

  • 服务客户端之间的远程调用

注册

  • Client端向Server端注册自身的元数据以供服务发现

续约

  • 通过发送心跳到Server以维持和更新注册表中服务实例元数据的有效性

  • 当在一定时长内,Server没有收到Client的心跳信息,将默认服务下线,会把服务实例的信息从注册表中删除

下线

  • Client在关闭时主动向Server注销服务实例元数据
  • 这时Client的服务实例数据将从Server的注册表中删除

获取注册表

  • Client向Server请求注册表信息,用于服务发现,从而发起服务间远程调用

客户端

拉取注册表 从注册表选一个调用

服务端

写个web server

功能

  • 定义注册表: Map<name,Map<id,InstanceInfo>>
  • 别人可以向我注册自己的信息
  • 别人可以从我这里拉取他人的注册信息
  • 我和我的同类可以共享注册表
  • eureka是用:jersey实现,也是个mvc框架,我们可以自己写个spring boot web实现

@Deprecated,暂时使用,要被废弃

@ImplementedBy,指定的接口实现类

EurekaClient实例化流程

Spring-boot 实例化过程:https://www.cnblogs.com/YC-L/p/14476347.html

eureka client 配置相关类

找到当前项目引入的jar包,spring-cloud-netflix-eureka-client-2.1.2.RELEASE下的 META-INF/spring.factories

Eureka Client 加载过程以及源码第3张

此文件中,有如下配置信息

org.springframework.boot.autoconfigure.EnableAutoConfiguration=
org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,
org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,
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.EurekaDiscoveryClientConfigServiceBootstrapConfiguration
  • EurekaClientAutoConfiguration,Eureka client自动配置类,负责Eureka client中关键beans的配置和初始化
  • RibbonEurekaAutoConfiguration,Ribbon负载均衡相关配置
  • EurekaDiscoveryClientConfiguration,配置自动注册和应用的健康检查器

EurekaDiscoveryClientConfiguration.class

注解 @ConditionalOnClass,若这个类存在,就加载这个bean,下面代码中,加载的这个类是EurekaClient

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.cloud.netflix.eureka;

import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.discovery.EurekaClient;
import com.netflix.discovery.EurekaClientConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.SimpleStatusAggregator;
import org.springframework.boot.actuate.health.StatusAggregator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.ConditionalOnBlockingDiscoveryEnabled;
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
import org.springframework.cloud.context.scope.refresh.RefreshScopeRefreshedEvent;
import org.springframework.cloud.netflix.eureka.serviceregistry.EurekaAutoServiceRegistration;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration(
    proxyBeanMethods = false
)
@EnableConfigurationProperties
@ConditionalOnClass({EurekaClientConfig.class})
@ConditionalOnProperty(
    value = {"eureka.client.enabled"},
    matchIfMissing = true
)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
public class EurekaDiscoveryClientConfiguration {
    public EurekaDiscoveryClientConfiguration() {
    }

    /** @deprecated */
    @Deprecated
    @Bean
    public EurekaDiscoveryClientConfiguration.Marker eurekaDiscoverClientMarker() {
        return new EurekaDiscoveryClientConfiguration.Marker();
    }

    @Bean
    @ConditionalOnMissingBean
    public EurekaDiscoveryClient discoveryClient(EurekaClient client, EurekaClientConfig clientConfig) {
        return new EurekaDiscoveryClient(client, clientConfig);
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({RefreshScopeRefreshedEvent.class})
    protected static class EurekaClientConfigurationRefresher implements ApplicationListener<RefreshScopeRefreshedEvent> {
        @Autowired(
            required = false
        )
        private EurekaClient eurekaClient;
        @Autowired(
            required = false
        )
        private EurekaAutoServiceRegistration autoRegistration;

        protected EurekaClientConfigurationRefresher() {
        }

        public void onApplicationEvent(RefreshScopeRefreshedEvent event) {
            if (this.eurekaClient != null) {
                this.eurekaClient.getApplications();
            }

            if (this.autoRegistration != null) {
                this.autoRegistration.stop();
                this.autoRegistration.start();
            }

        }
    }

    /** @deprecated */
    @Deprecated
    class Marker {
        Marker() {
        }
    }

    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnProperty(
        value = {"eureka.client.healthcheck.enabled"},
        matchIfMissing = false
    )
    protected static class EurekaHealthCheckHandlerConfiguration {
        @Autowired(
            required = false
        )
        private StatusAggregator statusAggregator = new SimpleStatusAggregator();

        protected EurekaHealthCheckHandlerConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean({HealthCheckHandler.class})
        public EurekaHealthCheckHandler eurekaHealthCheckHandler() {
            return new EurekaHealthCheckHandler(this.statusAggregator);
        }
    }
}

DefaultEurekaClientConfig.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.discovery;

import com.google.inject.ImplementedBy;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import java.util.List;
import javax.annotation.Nullable;

@ImplementedBy(DefaultEurekaClientConfig.class)
public interface EurekaClientConfig {
    int getRegistryFetchIntervalSeconds();

    int getInstanceInfoReplicationIntervalSeconds();

    int getInitialInstanceInfoReplicationIntervalSeconds();

    int getEurekaServiceUrlPollIntervalSeconds();

    String getProxyHost();

    String getProxyPort();

    String getProxyUserName();

    String getProxyPassword();

    /** @deprecated */
    boolean shouldGZipContent();

    int getEurekaServerReadTimeoutSeconds();

    int getEurekaServerConnectTimeoutSeconds();

    String getBackupRegistryImpl();

    int getEurekaServerTotalConnections();

    int getEurekaServerTotalConnectionsPerHost();

    String getEurekaServerURLContext();

    String getEurekaServerPort();

    String getEurekaServerDNSName();

    boolean shouldUseDnsForFetchingServiceUrls();

    boolean shouldRegisterWithEureka();

    default boolean shouldUnregisterOnShutdown() {
        return true;
    }

    boolean shouldPreferSameZoneEureka();

    boolean allowRedirects();

    boolean shouldLogDeltaDiff();

    boolean shouldDisableDelta();

    @Nullable
    String fetchRegistryForRemoteRegions();

    String getRegion();

    String[] getAvailabilityZones(String var1);

    List<String> getEurekaServerServiceUrls(String var1);

    boolean shouldFilterOnlyUpInstances();

    int getEurekaConnectionIdleTimeoutSeconds();

    boolean shouldFetchRegistry();

    @Nullable
    String getRegistryRefreshSingleVipAddress();

    int getHeartbeatExecutorThreadPoolSize();

    int getHeartbeatExecutorExponentialBackOffBound();

    int getCacheRefreshExecutorThreadPoolSize();

    int getCacheRefreshExecutorExponentialBackOffBound();

    String getDollarReplacement();

    String getEscapeCharReplacement();

    boolean shouldOnDemandUpdateStatusChange();

    default boolean shouldEnforceRegistrationAtInit() {
        return false;
    }

    String getEncoderName();

    String getDecoderName();

    String getClientDataAccept();

    String getExperimental(String var1);

    EurekaTransportConfig getTransportConfig();
}

查看其实现类DefaultEurekaClientConfig.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.discovery;

import com.google.inject.ProvidedBy;
import com.netflix.appinfo.EurekaAccept;
import com.netflix.config.DynamicPropertyFactory;
import com.netflix.config.DynamicStringProperty;
import com.netflix.discovery.internal.util.Archaius1Utils;
import com.netflix.discovery.providers.DefaultEurekaClientConfigProvider;
import com.netflix.discovery.shared.transport.DefaultEurekaTransportConfig;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Nullable;
import javax.inject.Singleton;

@Singleton
@ProvidedBy(DefaultEurekaClientConfigProvider.class)
public class DefaultEurekaClientConfig implements EurekaClientConfig {
    /** @deprecated */
    @Deprecated
    public static final String DEFAULT_NAMESPACE = "eureka.";
    public static final String DEFAULT_ZONE = "defaultZone";
    public static final String URL_SEPARATOR = "\s*,\s*";
    private final String namespace;
    private final DynamicPropertyFactory configInstance;
    private final EurekaTransportConfig transportConfig;

    public DefaultEurekaClientConfig() {
        this("eureka");
    }

    public DefaultEurekaClientConfig(String namespace) {
        this.namespace = namespace.endsWith(".") ? namespace : namespace + ".";
        this.configInstance = Archaius1Utils.initConfig("eureka-client");
        this.transportConfig = new DefaultEurekaTransportConfig(namespace, this.configInstance);
    }

    public int getRegistryFetchIntervalSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "client.refresh.interval", 30).get();
    }

    public int getInstanceInfoReplicationIntervalSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "appinfo.replicate.interval", 30).get();
    }

    public int getInitialInstanceInfoReplicationIntervalSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "appinfo.initial.replicate.time", 40).get();
    }

    public int getEurekaServiceUrlPollIntervalSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "serviceUrlPollIntervalMs", 300000).get() / 1000;
    }

    public String getProxyHost() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.proxyHost", (String)null).get();
    }

    public String getProxyPort() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.proxyPort", (String)null).get();
    }

    public String getProxyUserName() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.proxyUserName", (String)null).get();
    }

    public String getProxyPassword() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.proxyPassword", (String)null).get();
    }

    public boolean shouldGZipContent() {
        return this.configInstance.getBooleanProperty(this.namespace + "eurekaServer.gzipContent", true).get();
    }

    public int getEurekaServerReadTimeoutSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "eurekaServer.readTimeout", 8).get();
    }

    public int getEurekaServerConnectTimeoutSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "eurekaServer.connectTimeout", 5).get();
    }

    public String getBackupRegistryImpl() {
        return this.configInstance.getStringProperty(this.namespace + "backupregistry", (String)null).get();
    }

    public int getEurekaServerTotalConnections() {
        return this.configInstance.getIntProperty(this.namespace + "eurekaServer.maxTotalConnections", 200).get();
    }

    public int getEurekaServerTotalConnectionsPerHost() {
        return this.configInstance.getIntProperty(this.namespace + "eurekaServer.maxConnectionsPerHost", 50).get();
    }

    public String getEurekaServerURLContext() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.context", this.configInstance.getStringProperty(this.namespace + "context", (String)null).get()).get();
    }

    public String getEurekaServerPort() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.port", this.configInstance.getStringProperty(this.namespace + "port", (String)null).get()).get();
    }

    public String getEurekaServerDNSName() {
        return this.configInstance.getStringProperty(this.namespace + "eurekaServer.domainName", this.configInstance.getStringProperty(this.namespace + "domainName", (String)null).get()).get();
    }

    public boolean shouldUseDnsForFetchingServiceUrls() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldUseDns", false).get();
    }

    public boolean shouldRegisterWithEureka() {
        return this.configInstance.getBooleanProperty(this.namespace + "registration.enabled", true).get();
    }

    public boolean shouldUnregisterOnShutdown() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldUnregisterOnShutdown", true).get();
    }

    public boolean shouldPreferSameZoneEureka() {
        return this.configInstance.getBooleanProperty(this.namespace + "preferSameZone", true).get();
    }

    public boolean allowRedirects() {
        return this.configInstance.getBooleanProperty(this.namespace + "allowRedirects", false).get();
    }

    public boolean shouldLogDeltaDiff() {
        return this.configInstance.getBooleanProperty(this.namespace + "printDeltaFullDiff", false).get();
    }

    public boolean shouldDisableDelta() {
        return this.configInstance.getBooleanProperty(this.namespace + "disableDelta", false).get();
    }

    @Nullable
    public String fetchRegistryForRemoteRegions() {
        return this.configInstance.getStringProperty(this.namespace + "fetchRemoteRegionsRegistry", (String)null).get();
    }

    public String getRegion() {
        DynamicStringProperty defaultEurekaRegion = this.configInstance.getStringProperty("eureka.region", "us-east-1");
        return this.configInstance.getStringProperty(this.namespace + "region", defaultEurekaRegion.get()).get();
    }

    public String[] getAvailabilityZones(String region) {
        return this.configInstance.getStringProperty(this.namespace + region + "." + "availabilityZones", "defaultZone").get().split("\s*,\s*");
    }

    public List<String> getEurekaServerServiceUrls(String myZone) {
        String serviceUrls = this.configInstance.getStringProperty(this.namespace + "serviceUrl" + "." + myZone, (String)null).get();
        if (serviceUrls == null || serviceUrls.isEmpty()) {
            serviceUrls = this.configInstance.getStringProperty(this.namespace + "serviceUrl" + ".default", (String)null).get();
        }

        return (List)(serviceUrls != null ? Arrays.asList(serviceUrls.split("\s*,\s*")) : new ArrayList());
    }

    public boolean shouldFilterOnlyUpInstances() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldFilterOnlyUpInstances", true).get();
    }

    public int getEurekaConnectionIdleTimeoutSeconds() {
        return this.configInstance.getIntProperty(this.namespace + "eurekaserver.connectionIdleTimeoutInSeconds", 30).get();
    }

    public boolean shouldFetchRegistry() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldFetchRegistry", true).get();
    }

    public String getRegistryRefreshSingleVipAddress() {
        return this.configInstance.getStringProperty(this.namespace + "registryRefreshSingleVipAddress", (String)null).get();
    }

    public int getHeartbeatExecutorThreadPoolSize() {
        return this.configInstance.getIntProperty(this.namespace + "client.heartbeat.threadPoolSize", 5).get();
    }

    public int getHeartbeatExecutorExponentialBackOffBound() {
        return this.configInstance.getIntProperty(this.namespace + "client.heartbeat.exponentialBackOffBound", 10).get();
    }

    public int getCacheRefreshExecutorThreadPoolSize() {
        return this.configInstance.getIntProperty(this.namespace + "client.cacheRefresh.threadPoolSize", 5).get();
    }

    public int getCacheRefreshExecutorExponentialBackOffBound() {
        return this.configInstance.getIntProperty(this.namespace + "client.cacheRefresh.exponentialBackOffBound", 10).get();
    }

    public String getDollarReplacement() {
        return this.configInstance.getStringProperty(this.namespace + "dollarReplacement", "_-").get();
    }

    public String getEscapeCharReplacement() {
        return this.configInstance.getStringProperty(this.namespace + "escapeCharReplacement", "__").get();
    }

    public boolean shouldOnDemandUpdateStatusChange() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldOnDemandUpdateStatusChange", true).get();
    }

    public boolean shouldEnforceRegistrationAtInit() {
        return this.configInstance.getBooleanProperty(this.namespace + "shouldEnforceRegistrationAtInit", false).get();
    }

    public String getEncoderName() {
        return this.configInstance.getStringProperty(this.namespace + "encoderName", (String)null).get();
    }

    public String getDecoderName() {
        return this.configInstance.getStringProperty(this.namespace + "decoderName", (String)null).get();
    }

    public String getClientDataAccept() {
        return this.configInstance.getStringProperty(this.namespace + "clientDataAccept", EurekaAccept.full.name()).get();
    }

    public String getExperimental(String name) {
        return this.configInstance.getStringProperty(this.namespace + "experimental" + "." + name, (String)null).get();
    }

    public EurekaTransportConfig getTransportConfig() {
        return this.transportConfig;
    }
}

封装了Eureka Client和Eureka Server交互所需要的配置信息

eurekaClient实现类

Eureka Client 加载过程以及源码第4张

DiscoveryClient.class

用来服务发现的客户端接口,是客户端进行服务发现的核心接口,是spring cloud用来进行服务发现的顶级接口,在common中可以看到其地位

在Netflix Eureka和Consul中都有具体的实现类

org.springframework.cloud.client.discovery.DiscoveryClient的类注释:

Represents read operations commonly available to discovery services such as Netflix Eureka or consul.io

代表通用于服务发现的读操作,例如在 eureka或consul中

  • 有 String description();//获取实现类的描述
  • List<String> getServices();//获取所有服务实例id
  • List<ServiceInstance> getInstances(String serviceId);//通过服务id查询服务实例信息列表/p>
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.discovery;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.inject.Inject;
import com.netflix.appinfo.ApplicationInfoManager;
import com.netflix.appinfo.HealthCheckCallback;
import com.netflix.appinfo.HealthCheckCallbackToHandlerBridge;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.ApplicationInfoManager.StatusChangeListener;
import com.netflix.appinfo.InstanceInfo.ActionType;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.discovery.endpoint.EndpointUtils;
import com.netflix.discovery.endpoint.EndpointUtils.DiscoveryUrlType;
import com.netflix.discovery.endpoint.EndpointUtils.InstanceInfoBasedUrlRandomizer;
import com.netflix.discovery.endpoint.EndpointUtils.ServiceUrlRandomizer;
import com.netflix.discovery.shared.Application;
import com.netflix.discovery.shared.Applications;
import com.netflix.discovery.shared.resolver.ClosableResolver;
import com.netflix.discovery.shared.resolver.EndpointRandomizer;
import com.netflix.discovery.shared.resolver.ResolverUtils;
import com.netflix.discovery.shared.resolver.aws.ApplicationsResolver.ApplicationsSource;
import com.netflix.discovery.shared.transport.EurekaHttpClient;
import com.netflix.discovery.shared.transport.EurekaHttpClientFactory;
import com.netflix.discovery.shared.transport.EurekaHttpClients;
import com.netflix.discovery.shared.transport.EurekaHttpResponse;
import com.netflix.discovery.shared.transport.EurekaTransportConfig;
import com.netflix.discovery.shared.transport.TransportClientFactory;
import com.netflix.discovery.shared.transport.jersey.EurekaJerseyClient;
import com.netflix.discovery.shared.transport.jersey.Jersey1DiscoveryClientOptionalArgs;
import com.netflix.discovery.shared.transport.jersey.Jersey1TransportClientFactories;
import com.netflix.discovery.shared.transport.jersey.TransportClientFactories;
import com.netflix.discovery.util.ThresholdLevelsMetric;
import com.netflix.servo.annotations.DataSourceType;
import com.netflix.servo.annotations.Monitor;
import com.netflix.servo.monitor.Counter;
import com.netflix.servo.monitor.Monitors;
import com.netflix.servo.monitor.Stopwatch;
import com.netflix.servo.monitor.Timer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
import javax.annotation.PreDestroy;
import javax.inject.Provider;
import javax.inject.Singleton;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.ws.rs.core.Response.Status;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class DiscoveryClient implements EurekaClient {
    private static final Logger logger = LoggerFactory.getLogger(DiscoveryClient.class);
    public static final String HTTP_X_DISCOVERY_ALLOW_REDIRECT = "X-Discovery-AllowRedirect";
    private static final String VALUE_DELIMITER = ",";
    private static final String COMMA_STRING = ",";
    /** @deprecated */
    @Deprecated
    private static EurekaClientConfig staticClientConfig;
    private static final String PREFIX = "DiscoveryClient_";
    private final Counter RECONCILE_HASH_CODES_MISMATCH;
    private final Timer FETCH_REGISTRY_TIMER;
    private final Counter REREGISTER_COUNTER;
    private final ScheduledExecutorService scheduler;
    private final ThreadPoolExecutor heartbeatExecutor;
    private final ThreadPoolExecutor cacheRefreshExecutor;
    private TimedSupervisorTask cacheRefreshTask;
    private TimedSupervisorTask heartbeatTask;
    private final Provider<HealthCheckHandler> healthCheckHandlerProvider;
    private final Provider<HealthCheckCallback> healthCheckCallbackProvider;
    private final PreRegistrationHandler preRegistrationHandler;
    private final AtomicReference<Applications> localRegionApps;
    private final Lock fetchRegistryUpdateLock;
    private final AtomicLong fetchRegistryGeneration;
    private final ApplicationInfoManager applicationInfoManager;
    private final InstanceInfo instanceInfo;
    private final AtomicReference<String> remoteRegionsToFetch;
    private final AtomicReference<String[]> remoteRegionsRef;
    private final InstanceRegionChecker instanceRegionChecker;
    private final ServiceUrlRandomizer urlRandomizer;
    private final EndpointRandomizer endpointRandomizer;
    private final Provider<BackupRegistry> backupRegistryProvider;
    private final DiscoveryClient.EurekaTransport eurekaTransport;
    private final AtomicReference<HealthCheckHandler> healthCheckHandlerRef;
    private volatile Map<String, Applications> remoteRegionVsApps;
    private volatile InstanceStatus lastRemoteInstanceStatus;
    private final CopyOnWriteArraySet<EurekaEventListener> eventListeners;
    private String appPathIdentifier;
    private StatusChangeListener statusChangeListener;
    private InstanceInfoReplicator instanceInfoReplicator;
    private volatile int registrySize;
    private volatile long lastSuccessfulRegistryFetchTimestamp;
    private volatile long lastSuccessfulHeartbeatTimestamp;
    private final ThresholdLevelsMetric heartbeatStalenessMonitor;
    private final ThresholdLevelsMetric registryStalenessMonitor;
    private final AtomicBoolean isShutdown;
    protected final EurekaClientConfig clientConfig;
    protected final EurekaTransportConfig transportConfig;
    private final long initTimestampMs;

    /** @deprecated */
    @Deprecated
    public DiscoveryClient(InstanceInfo myInfo, EurekaClientConfig config) {
        this((InstanceInfo)myInfo, config, (DiscoveryClient.DiscoveryClientOptionalArgs)null);
    }

    /** @deprecated */
    @Deprecated
    public DiscoveryClient(InstanceInfo myInfo, EurekaClientConfig config, DiscoveryClient.DiscoveryClientOptionalArgs args) {
        this(ApplicationInfoManager.getInstance(), config, args);
    }

    /** @deprecated */
    @Deprecated
    public DiscoveryClient(InstanceInfo myInfo, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args) {
        this(ApplicationInfoManager.getInstance(), config, args);
    }

    public DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config) {
        this((ApplicationInfoManager)applicationInfoManager, config, (DiscoveryClient.DiscoveryClientOptionalArgs)null);
    }

    /** @deprecated */
    @Deprecated
    public DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, DiscoveryClient.DiscoveryClientOptionalArgs args) {
        this((ApplicationInfoManager)applicationInfoManager, config, (AbstractDiscoveryClientOptionalArgs)args);
    }

    public DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args) {
        this(applicationInfoManager, config, args, ResolverUtils::randomize);
    }

    public DiscoveryClient(ApplicationInfoManager applicationInfoManager, final EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, EndpointRandomizer randomizer) {
        this(applicationInfoManager, config, args, new Provider<BackupRegistry>() {
            private volatile BackupRegistry backupRegistryInstance;

            public synchronized BackupRegistry get() {
                if (this.backupRegistryInstance == null) {
                    String backupRegistryClassName = config.getBackupRegistryImpl();
                    if (null != backupRegistryClassName) {
                        try {
                            this.backupRegistryInstance = (BackupRegistry)Class.forName(backupRegistryClassName).newInstance();
                            DiscoveryClient.logger.info("Enabled backup registry of type {}", this.backupRegistryInstance.getClass());
                        } catch (InstantiationException var3) {
                            DiscoveryClient.logger.error("Error instantiating BackupRegistry.", var3);
                        } catch (IllegalAccessException var4) {
                            DiscoveryClient.logger.error("Error instantiating BackupRegistry.", var4);
                        } catch (ClassNotFoundException var5) {
                            DiscoveryClient.logger.error("Error instantiating BackupRegistry.", var5);
                        }
                    }

                    if (this.backupRegistryInstance == null) {
                        DiscoveryClient.logger.warn("Using default backup registry implementation which does not do anything.");
                        this.backupRegistryInstance = new NotImplementedRegistryImpl();
                    }
                }

                return this.backupRegistryInstance;
            }
        }, randomizer);
    }

    /** @deprecated */
    @Deprecated
    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider) {
        this(applicationInfoManager, config, args, backupRegistryProvider, ResolverUtils::randomize);
    }

    @Inject
    DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider, EndpointRandomizer endpointRandomizer) {
        this.RECONCILE_HASH_CODES_MISMATCH = Monitors.newCounter("DiscoveryClient_ReconcileHashCodeMismatch");
        this.FETCH_REGISTRY_TIMER = Monitors.newTimer("DiscoveryClient_FetchRegistry");
        this.REREGISTER_COUNTER = Monitors.newCounter("DiscoveryClient_Reregister");
        this.localRegionApps = new AtomicReference();
        this.fetchRegistryUpdateLock = new ReentrantLock();
        this.healthCheckHandlerRef = new AtomicReference();
        this.remoteRegionVsApps = new ConcurrentHashMap();
        this.lastRemoteInstanceStatus = InstanceStatus.UNKNOWN;
        this.eventListeners = new CopyOnWriteArraySet();
        this.registrySize = 0;
        this.lastSuccessfulRegistryFetchTimestamp = -1L;
        this.lastSuccessfulHeartbeatTimestamp = -1L;
        this.isShutdown = new AtomicBoolean(false);
        if (args != null) {
            this.healthCheckHandlerProvider = args.healthCheckHandlerProvider;
            this.healthCheckCallbackProvider = args.healthCheckCallbackProvider;
            this.eventListeners.addAll(args.getEventListeners());
            this.preRegistrationHandler = args.preRegistrationHandler;
        } else {
            this.healthCheckCallbackProvider = null;
            this.healthCheckHandlerProvider = null;
            this.preRegistrationHandler = null;
        }

        this.applicationInfoManager = applicationInfoManager;
        InstanceInfo myInfo = applicationInfoManager.getInfo();
        this.clientConfig = config;
        staticClientConfig = this.clientConfig;
        this.transportConfig = config.getTransportConfig();
        this.instanceInfo = myInfo;
        if (myInfo != null) {
            this.appPathIdentifier = this.instanceInfo.getAppName() + "/" + this.instanceInfo.getId();
        } else {
            logger.warn("Setting instanceInfo to a passed in null value");
        }

        this.backupRegistryProvider = backupRegistryProvider;
        this.endpointRandomizer = endpointRandomizer;
        this.urlRandomizer = new InstanceInfoBasedUrlRandomizer(this.instanceInfo);
        this.localRegionApps.set(new Applications());
        this.fetchRegistryGeneration = new AtomicLong(0L);
        this.remoteRegionsToFetch = new AtomicReference(this.clientConfig.fetchRegistryForRemoteRegions());
        this.remoteRegionsRef = new AtomicReference(this.remoteRegionsToFetch.get() == null ? null : ((String)this.remoteRegionsToFetch.get()).split(","));
        if (config.shouldFetchRegistry()) {
            this.registryStalenessMonitor = new ThresholdLevelsMetric(this, "eurekaClient.registry.lastUpdateSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
        } else {
            this.registryStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
        }

        if (config.shouldRegisterWithEureka()) {
            this.heartbeatStalenessMonitor = new ThresholdLevelsMetric(this, "eurekaClient.registration.lastHeartbeatSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L});
        } else {
            this.heartbeatStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC;
        }

        logger.info("Initializing Eureka in region {}", this.clientConfig.getRegion());
        if (!config.shouldRegisterWithEureka() && !config.shouldFetchRegistry()) {
            logger.info("Client configured to neither register nor query for data.");
            this.scheduler = null;
            this.heartbeatExecutor = null;
            this.cacheRefreshExecutor = null;
            this.eurekaTransport = null;
            this.instanceRegionChecker = new InstanceRegionChecker(new PropertyBasedAzToRegionMapper(config), this.clientConfig.getRegion());
            DiscoveryManager.getInstance().setDiscoveryClient(this);
            DiscoveryManager.getInstance().setEurekaClientConfig(config);
            this.initTimestampMs = System.currentTimeMillis();
            logger.info("Discovery Client initialized at timestamp {} with initial instances count: {}", this.initTimestampMs, this.getApplications().size());
        } else {
            try {
                this.scheduler = Executors.newScheduledThreadPool(2, (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-%d").setDaemon(true).build());
                this.heartbeatExecutor = new ThreadPoolExecutor(1, this.clientConfig.getHeartbeatExecutorThreadPoolSize(), 0L, TimeUnit.SECONDS, new SynchronousQueue(), (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-HeartbeatExecutor-%d").setDaemon(true).build());
                this.cacheRefreshExecutor = new ThreadPoolExecutor(1, this.clientConfig.getCacheRefreshExecutorThreadPoolSize(), 0L, TimeUnit.SECONDS, new SynchronousQueue(), (new ThreadFactoryBuilder()).setNameFormat("DiscoveryClient-CacheRefreshExecutor-%d").setDaemon(true).build());
                this.eurekaTransport = new DiscoveryClient.EurekaTransport();
                this.scheduleServerEndpointTask(this.eurekaTransport, args);
                Object azToRegionMapper;
                if (this.clientConfig.shouldUseDnsForFetchingServiceUrls()) {
                    azToRegionMapper = new DNSBasedAzToRegionMapper(this.clientConfig);
                } else {
                    azToRegionMapper = new PropertyBasedAzToRegionMapper(this.clientConfig);
                }

                if (null != this.remoteRegionsToFetch.get()) {
                    ((AzToRegionMapper)azToRegionMapper).setRegionsToFetch(((String)this.remoteRegionsToFetch.get()).split(","));
                }

                this.instanceRegionChecker = new InstanceRegionChecker((AzToRegionMapper)azToRegionMapper, this.clientConfig.getRegion());
            } catch (Throwable var10) {
                throw new RuntimeException("Failed to initialize DiscoveryClient!", var10);
            }

            if (this.clientConfig.shouldFetchRegistry() && !this.fetchRegistry(false)) {
                this.fetchRegistryFromBackup();
            }

            if (this.preRegistrationHandler != null) {
                this.preRegistrationHandler.beforeRegistration();
            }

            if (this.clientConfig.shouldRegisterWithEureka() && this.clientConfig.shouldEnforceRegistrationAtInit()) {
                try {
                    if (!this.register()) {
                        throw new IllegalStateException("Registration error at startup. Invalid server response.");
                    }
                } catch (Throwable var9) {
                    logger.error("Registration error at startup: {}", var9.getMessage());
                    throw new IllegalStateException(var9);
                }
            }

            this.initScheduledTasks();

            try {
                Monitors.registerObject(this);
            } catch (Throwable var8) {
                logger.warn("Cannot register timers", var8);
            }

            DiscoveryManager.getInstance().setDiscoveryClient(this);
            DiscoveryManager.getInstance().setEurekaClientConfig(config);
            this.initTimestampMs = System.currentTimeMillis();
            logger.info("Discovery Client initialized at timestamp {} with initial instances count: {}", this.initTimestampMs, this.getApplications().size());
        }
    }

    private void scheduleServerEndpointTask(DiscoveryClient.EurekaTransport eurekaTransport, AbstractDiscoveryClientOptionalArgs args) {
        Collection<?> additionalFilters = args == null ? Collections.emptyList() : args.additionalFilters;
        EurekaJerseyClient providedJerseyClient = args == null ? null : args.eurekaJerseyClient;
        TransportClientFactories argsTransportClientFactories = null;
        if (args != null && args.getTransportClientFactories() != null) {
            argsTransportClientFactories = args.getTransportClientFactories();
        }

        TransportClientFactories transportClientFactories = argsTransportClientFactories == null ? new Jersey1TransportClientFactories() : argsTransportClientFactories;
        Optional<SSLContext> sslContext = args == null ? Optional.empty() : args.getSSLContext();
        Optional<HostnameVerifier> hostnameVerifier = args == null ? Optional.empty() : args.getHostnameVerifier();
        eurekaTransport.transportClientFactory = providedJerseyClient == null ? ((TransportClientFactories)transportClientFactories).newTransportClientFactory(this.clientConfig, (Collection)additionalFilters, this.applicationInfoManager.getInfo(), sslContext, hostnameVerifier) : ((TransportClientFactories)transportClientFactories).newTransportClientFactory((Collection)additionalFilters, providedJerseyClient);
        ApplicationsSource applicationsSource = new ApplicationsSource() {
            public Applications getApplications(int stalenessThreshold, TimeUnit timeUnit) {
                long thresholdInMs = TimeUnit.MILLISECONDS.convert((long)stalenessThreshold, timeUnit);
                long delay = DiscoveryClient.this.getLastSuccessfulRegistryFetchTimePeriod();
                if (delay > thresholdInMs) {
                    DiscoveryClient.logger.info("Local registry is too stale for local lookup. Threshold:{}, actual:{}", thresholdInMs, delay);
                    return null;
                } else {
                    return (Applications)DiscoveryClient.this.localRegionApps.get();
                }
            }
        };
        eurekaTransport.bootstrapResolver = EurekaHttpClients.newBootstrapResolver(this.clientConfig, this.transportConfig, eurekaTransport.transportClientFactory, this.applicationInfoManager.getInfo(), applicationsSource, this.endpointRandomizer);
        EurekaHttpClientFactory newQueryClientFactory;
        EurekaHttpClient newQueryClient;
        if (this.clientConfig.shouldRegisterWithEureka()) {
            newQueryClientFactory = null;
            newQueryClient = null;

            try {
                newQueryClientFactory = EurekaHttpClients.registrationClientFactory(eurekaTransport.bootstrapResolver, eurekaTransport.transportClientFactory, this.transportConfig);
                newQueryClient = newQueryClientFactory.newClient();
            } catch (Exception var14) {
                logger.warn("Transport initialization failure", var14);
            }

            eurekaTransport.registrationClientFactory = newQueryClientFactory;
            eurekaTransport.registrationClient = newQueryClient;
        }

        if (this.clientConfig.shouldFetchRegistry()) {
            newQueryClientFactory = null;
            newQueryClient = null;

            try {
                newQueryClientFactory = EurekaHttpClients.queryClientFactory(eurekaTransport.bootstrapResolver, eurekaTransport.transportClientFactory, this.clientConfig, this.transportConfig, this.applicationInfoManager.getInfo(), applicationsSource, this.endpointRandomizer);
                newQueryClient = newQueryClientFactory.newClient();
            } catch (Exception var13) {
                logger.warn("Transport initialization failure", var13);
            }

            eurekaTransport.queryClientFactory = newQueryClientFactory;
            eurekaTransport.queryClient = newQueryClient;
        }

    }

    public EurekaClientConfig getEurekaClientConfig() {
        return this.clientConfig;
    }

    public ApplicationInfoManager getApplicationInfoManager() {
        return this.applicationInfoManager;
    }

    public Application getApplication(String appName) {
        return this.getApplications().getRegisteredApplications(appName);
    }

    public Applications getApplications() {
        return (Applications)this.localRegionApps.get();
    }

    public Applications getApplicationsForARegion(@Nullable String region) {
        return this.instanceRegionChecker.isLocalRegion(region) ? (Applications)this.localRegionApps.get() : (Applications)this.remoteRegionVsApps.get(region);
    }

    public Set<String> getAllKnownRegions() {
        String localRegion = this.instanceRegionChecker.getLocalRegion();
        if (!this.remoteRegionVsApps.isEmpty()) {
            Set<String> regions = this.remoteRegionVsApps.keySet();
            Set<String> toReturn = new HashSet(regions);
            toReturn.add(localRegion);
            return toReturn;
        } else {
            return Collections.singleton(localRegion);
        }
    }

    public List<InstanceInfo> getInstancesById(String id) {
        List<InstanceInfo> instancesList = new ArrayList();
        Iterator var3 = this.getApplications().getRegisteredApplications().iterator();

        while(var3.hasNext()) {
            Application app = (Application)var3.next();
            InstanceInfo instanceInfo = app.getByInstanceId(id);
            if (instanceInfo != null) {
                instancesList.add(instanceInfo);
            }
        }

        return instancesList;
    }

    /** @deprecated */
    @Deprecated
    public void registerHealthCheckCallback(HealthCheckCallback callback) {
        if (this.instanceInfo == null) {
            logger.error("Cannot register a listener for instance info since it is null!");
        }

        if (callback != null) {
            this.healthCheckHandlerRef.set(new HealthCheckCallbackToHandlerBridge(callback));
        }

    }

    public void registerHealthCheck(HealthCheckHandler healthCheckHandler) {
        if (this.instanceInfo == null) {
            logger.error("Cannot register a healthcheck handler when instance info is null!");
        }

        if (healthCheckHandler != null) {
            this.healthCheckHandlerRef.set(healthCheckHandler);
            if (this.instanceInfoReplicator != null) {
                this.instanceInfoReplicator.onDemandUpdate();
            }
        }

    }

    public void registerEventListener(EurekaEventListener eventListener) {
        this.eventListeners.add(eventListener);
    }

    public boolean unregisterEventListener(EurekaEventListener eventListener) {
        return this.eventListeners.remove(eventListener);
    }

    public List<InstanceInfo> getInstancesByVipAddress(String vipAddress, boolean secure) {
        return this.getInstancesByVipAddress(vipAddress, secure, this.instanceRegionChecker.getLocalRegion());
    }

    public List<InstanceInfo> getInstancesByVipAddress(String vipAddress, boolean secure, @Nullable String region) {
        if (vipAddress == null) {
            throw new IllegalArgumentException("Supplied VIP Address cannot be null");
        } else {
            Applications applications;
            if (this.instanceRegionChecker.isLocalRegion(region)) {
                applications = (Applications)this.localRegionApps.get();
            } else {
                applications = (Applications)this.remoteRegionVsApps.get(region);
                if (null == applications) {
                    logger.debug("No applications are defined for region {}, so returning an empty instance list for vip address {}.", region, vipAddress);
                    return Collections.emptyList();
                }
            }

            return !secure ? applications.getInstancesByVirtualHostName(vipAddress) : applications.getInstancesBySecureVirtualHostName(vipAddress);
        }
    }

    public List<InstanceInfo> getInstancesByVipAddressAndAppName(String vipAddress, String appName, boolean secure) {
        List<InstanceInfo> result = new ArrayList();
        if (vipAddress == null && appName == null) {
            throw new IllegalArgumentException("Supplied VIP Address and application name cannot both be null");
        } else if (vipAddress != null && appName == null) {
            return this.getInstancesByVipAddress(vipAddress, secure);
        } else if (vipAddress == null && appName != null) {
            Application application = this.getApplication(appName);
            if (application != null) {
                result = application.getInstances();
            }

            return (List)result;
        } else {
            Iterator var6 = this.getApplications().getRegisteredApplications().iterator();

            label67:
            while(var6.hasNext()) {
                Application app = (Application)var6.next();
                Iterator var8 = app.getInstances().iterator();

                while(true) {
                    while(true) {
                        String instanceVipAddress;
                        InstanceInfo instance;
                        do {
                            if (!var8.hasNext()) {
                                continue label67;
                            }

                            instance = (InstanceInfo)var8.next();
                            if (secure) {
                                instanceVipAddress = instance.getSecureVipAddress();
                            } else {
                                instanceVipAddress = instance.getVIPAddress();
                            }
                        } while(instanceVipAddress == null);

                        String[] instanceVipAddresses = instanceVipAddress.split(",");
                        String[] var11 = instanceVipAddresses;
                        int var12 = instanceVipAddresses.length;

                        for(int var13 = 0; var13 < var12; ++var13) {
                            String vipAddressFromList = var11[var13];
                            if (vipAddress.equalsIgnoreCase(vipAddressFromList.trim()) && appName.equalsIgnoreCase(instance.getAppName())) {
                                ((List)result).add(instance);
                                break;
                            }
                        }
                    }
                }
            }

            return (List)result;
        }
    }

    public InstanceInfo getNextServerFromEureka(String virtualHostname, boolean secure) {
        List<InstanceInfo> instanceInfoList = this.getInstancesByVipAddress(virtualHostname, secure);
        if (instanceInfoList != null && !instanceInfoList.isEmpty()) {
            Applications apps = (Applications)this.localRegionApps.get();
            int index = (int)(apps.getNextIndex(virtualHostname, secure).incrementAndGet() % (long)instanceInfoList.size());
            return (InstanceInfo)instanceInfoList.get(index);
        } else {
            throw new RuntimeException("No matches for the virtual host name :" + virtualHostname);
        }
    }

    public Applications getApplications(String serviceUrl) {
        try {
            EurekaHttpResponse<Applications> response = this.clientConfig.getRegistryRefreshSingleVipAddress() == null ? this.eurekaTransport.queryClient.getApplications(new String[0]) : this.eurekaTransport.queryClient.getVip(this.clientConfig.getRegistryRefreshSingleVipAddress(), new String[0]);
            if (response.getStatusCode() == Status.OK.getStatusCode()) {
                logger.debug("DiscoveryClient_{} -  refresh status: {}", this.appPathIdentifier, response.getStatusCode());
                return (Applications)response.getEntity();
            }

            logger.error("DiscoveryClient_{} - was unable to refresh its cache! status = {}", this.appPathIdentifier, response.getStatusCode());
        } catch (Throwable var3) {
            logger.error("DiscoveryClient_{} - was unable to refresh its cache! status = {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});
        }

        return null;
    }

    boolean register() throws Throwable {
        logger.info("DiscoveryClient_{}: registering service...", this.appPathIdentifier);

        EurekaHttpResponse httpResponse;
        try {
            httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo);
        } catch (Exception var3) {
            logger.warn("DiscoveryClient_{} - registration failed {}", new Object[]{this.appPathIdentifier, var3.getMessage(), var3});
            throw var3;
        }

        if (logger.isInfoEnabled()) {
            logger.info("DiscoveryClient_{} - registration status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
        }

        return httpResponse.getStatusCode() == Status.NO_CONTENT.getStatusCode();
    }

    boolean renew() {
        try {
            EurekaHttpResponse<InstanceInfo> httpResponse = this.eurekaTransport.registrationClient.sendHeartBeat(this.instanceInfo.getAppName(), this.instanceInfo.getId(), this.instanceInfo, (InstanceStatus)null);
            logger.debug("DiscoveryClient_{} - Heartbeat status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
            if (httpResponse.getStatusCode() == Status.NOT_FOUND.getStatusCode()) {
                this.REREGISTER_COUNTER.increment();
                logger.info("DiscoveryClient_{} - Re-registering apps/{}", this.appPathIdentifier, this.instanceInfo.getAppName());
                long timestamp = this.instanceInfo.setIsDirtyWithTime();
                boolean success = this.register();
                if (success) {
                    this.instanceInfo.unsetIsDirty(timestamp);
                }

                return success;
            } else {
                return httpResponse.getStatusCode() == Status.OK.getStatusCode();
            }
        } catch (Throwable var5) {
            logger.error("DiscoveryClient_{} - was unable to send heartbeat!", this.appPathIdentifier, var5);
            return false;
        }
    }

    /** @deprecated */
    @Deprecated
    public List<String> getServiceUrlsFromConfig(String instanceZone, boolean preferSameZone) {
        return EndpointUtils.getServiceUrlsFromConfig(this.clientConfig, instanceZone, preferSameZone);
    }

    @PreDestroy
    public synchronized void shutdown() {
        if (this.isShutdown.compareAndSet(false, true)) {
            logger.info("Shutting down DiscoveryClient ...");
            if (this.statusChangeListener != null && this.applicationInfoManager != null) {
                this.applicationInfoManager.unregisterStatusChangeListener(this.statusChangeListener.getId());
            }

            this.cancelScheduledTasks();
            if (this.applicationInfoManager != null && this.clientConfig.shouldRegisterWithEureka() && this.clientConfig.shouldUnregisterOnShutdown()) {
                this.applicationInfoManager.setInstanceStatus(InstanceStatus.DOWN);
                this.unregister();
            }

            if (this.eurekaTransport != null) {
                this.eurekaTransport.shutdown();
            }

            this.heartbeatStalenessMonitor.shutdown();
            this.registryStalenessMonitor.shutdown();
            Monitors.unregisterObject(this);
            logger.info("Completed shut down of DiscoveryClient");
        }

    }

    void unregister() {
        if (this.eurekaTransport != null && this.eurekaTransport.registrationClient != null) {
            try {
                logger.info("Unregistering ...");
                EurekaHttpResponse<Void> httpResponse = this.eurekaTransport.registrationClient.cancel(this.instanceInfo.getAppName(), this.instanceInfo.getId());
                logger.info("DiscoveryClient_{} - deregister  status: {}", this.appPathIdentifier, httpResponse.getStatusCode());
            } catch (Exception var2) {
                logger.error("DiscoveryClient_{} - de-registration failed{}", new Object[]{this.appPathIdentifier, var2.getMessage(), var2});
            }
        }

    }

    private boolean fetchRegistry(boolean forceFullRegistryFetch) {
        Stopwatch tracer = this.FETCH_REGISTRY_TIMER.start();

        label122: {
            boolean var4;
            try {
                Applications applications = this.getApplications();
                if (!this.clientConfig.shouldDisableDelta() && Strings.isNullOrEmpty(this.clientConfig.getRegistryRefreshSingleVipAddress()) && !forceFullRegistryFetch && applications != null && applications.getRegisteredApplications().size() != 0 && applications.getVersion() != -1L) {
                    this.getAndUpdateDelta(applications);
                } else {
                    logger.info("Disable delta property : {}", this.clientConfig.shouldDisableDelta());
                    logger.info("Single vip registry refresh property : {}", this.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() == -1L);
                    this.getAndStoreFullRegistry();
                }

                applications.setAppsHashCode(applications.getReconcileHashCode());
                this.logTotalInstances();
                break label122;
            } catch (Throwable var8) {
                logger.error("DiscoveryClient_{} - was unable to refresh its cache! status = {}", new Object[]{this.appPathIdentifier, var8.getMessage(), var8});
                var4 = false;
            } finally {
                if (tracer != null) {
                    tracer.stop();
                }

            }

            return var4;
        }

        this.onCacheRefreshed();
        this.updateInstanceRemoteStatus();
        return true;
    }

    private synchronized void updateInstanceRemoteStatus() {
        InstanceStatus currentRemoteInstanceStatus = null;
        if (this.instanceInfo.getAppName() != null) {
            Application app = this.getApplication(this.instanceInfo.getAppName());
            if (app != null) {
                InstanceInfo remoteInstanceInfo = app.getByInstanceId(this.instanceInfo.getId());
                if (remoteInstanceInfo != null) {
                    currentRemoteInstanceStatus = remoteInstanceInfo.getStatus();
                }
            }
        }

        if (currentRemoteInstanceStatus == null) {
            currentRemoteInstanceStatus = InstanceStatus.UNKNOWN;
        }

        if (this.lastRemoteInstanceStatus != currentRemoteInstanceStatus) {
            this.onRemoteStatusChanged(this.lastRemoteInstanceStatus, currentRemoteInstanceStatus);
            this.lastRemoteInstanceStatus = currentRemoteInstanceStatus;
        }

    }

    public InstanceStatus getInstanceRemoteStatus() {
        return this.lastRemoteInstanceStatus;
    }

    private String getReconcileHashCode(Applications applications) {
        TreeMap<String, AtomicInteger> instanceCountMap = new TreeMap();
        if (this.isFetchingRemoteRegionRegistries()) {
            Iterator var3 = this.remoteRegionVsApps.values().iterator();

            while(var3.hasNext()) {
                Applications remoteApp = (Applications)var3.next();
                remoteApp.populateInstanceCountMap(instanceCountMap);
            }
        }

        applications.populateInstanceCountMap(instanceCountMap);
        return Applications.getReconcileHashCode(instanceCountMap);
    }

    private void getAndStoreFullRegistry() throws Throwable {
        long currentUpdateGeneration = this.fetchRegistryGeneration.get();
        logger.info("Getting all instance registry info from the eureka server");
        Applications apps = null;
        EurekaHttpResponse<Applications> httpResponse = this.clientConfig.getRegistryRefreshSingleVipAddress() == null ? this.eurekaTransport.queryClient.getApplications((String[])this.remoteRegionsRef.get()) : this.eurekaTransport.queryClient.getVip(this.clientConfig.getRegistryRefreshSingleVipAddress(), (String[])this.remoteRegionsRef.get());
        if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
            apps = (Applications)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");
        } else if (this.fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1L)) {
            this.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 {
        long currentUpdateGeneration = this.fetchRegistryGeneration.get();
        Applications delta = null;
        EurekaHttpResponse<Applications> httpResponse = this.eurekaTransport.queryClient.getDelta((String[])this.remoteRegionsRef.get());
        if (httpResponse.getStatusCode() == Status.OK.getStatusCode()) {
            delta = (Applications)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.");
            this.getAndStoreFullRegistry();
        } else if (this.fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1L)) {
            logger.debug("Got delta update with apps hashcode {}", delta.getAppsHashCode());
            String reconcileHashCode = "";
            if (this.fetchRegistryUpdateLock.tryLock()) {
                try {
                    this.updateDelta(delta);
                    reconcileHashCode = this.getReconcileHashCode(applications);
                } finally {
                    this.fetchRegistryUpdateLock.unlock();
                }
            } else {
                logger.warn("Cannot acquire update lock, aborting getAndUpdateDelta");
            }

            if (!reconcileHashCode.equals(delta.getAppsHashCode()) || this.clientConfig.shouldLogDeltaDiff()) {
                this.reconcileAndLogDifference(delta, reconcileHashCode);
            }
        } 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 logTotalInstances() {
        if (logger.isDebugEnabled()) {
            int totInstances = 0;

            Application application;
            for(Iterator var2 = this.getApplications().getRegisteredApplications().iterator(); var2.hasNext(); totInstances += application.getInstancesAsIsFromEureka().size()) {
                application = (Application)var2.next();
            }

            logger.debug("The total number of all instances in the client now is {}", totInstances);
        }

    }

    private void reconcileAndLogDifference(Applications delta, String reconcileHashCode) throws Throwable {
        logger.debug("The Reconcile hashcodes do not match, client : {}, server : {}. Getting the full registry", reconcileHashCode, delta.getAppsHashCode());
        this.RECONCILE_HASH_CODES_MISMATCH.increment();
        long currentUpdateGeneration = this.fetchRegistryGeneration.get();
        EurekaHttpResponse<Applications> httpResponse = this.clientConfig.getRegistryRefreshSingleVipAddress() == null ? this.eurekaTransport.queryClient.getApplications((String[])this.remoteRegionsRef.get()) : this.eurekaTransport.queryClient.getVip(this.clientConfig.getRegistryRefreshSingleVipAddress(), (String[])this.remoteRegionsRef.get());
        Applications serverApps = (Applications)httpResponse.getEntity();
        if (serverApps == null) {
            logger.warn("Cannot fetch full registry from the server; reconciliation failure");
        } else {
            if (this.fetchRegistryGeneration.compareAndSet(currentUpdateGeneration, currentUpdateGeneration + 1L)) {
                this.localRegionApps.set(this.filterAndShuffle(serverApps));
                this.getApplications().setVersion(delta.getVersion());
                logger.debug("The Reconcile hashcodes after complete sync up, client : {}, server : {}.", this.getApplications().getReconcileHashCode(), delta.getAppsHashCode());
            } else {
                logger.warn("Not setting the applications map as another thread has advanced the update generation");
            }

        }
    }

    private void updateDelta(Applications delta) {
        int deltaCount = 0;
        Iterator var3 = delta.getRegisteredApplications().iterator();

        while(var3.hasNext()) {
            Application app = (Application)var3.next();
            Iterator var5 = app.getInstances().iterator();

            while(var5.hasNext()) {
                InstanceInfo instance = (InstanceInfo)var5.next();
                Applications applications = this.getApplications();
                String instanceRegion = this.instanceRegionChecker.getInstanceRegion(instance);
                if (!this.instanceRegionChecker.isLocalRegion(instanceRegion)) {
                    Applications remoteApps = (Applications)this.remoteRegionVsApps.get(instanceRegion);
                    if (null == remoteApps) {
                        remoteApps = new Applications();
                        this.remoteRegionVsApps.put(instanceRegion, remoteApps);
                    }

                    applications = remoteApps;
                }

                ++deltaCount;
                Application existingApp;
                if (ActionType.ADDED.equals(instance.getActionType())) {
                    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())) {
                    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())) {
                    existingApp = applications.getRegisteredApplications(instance.getAppName());
                    if (existingApp != null) {
                        logger.debug("Deleted instance {} to the existing apps ", instance.getId());
                        existingApp.removeInstance(instance);
                        if (existingApp.getInstancesAsIsFromEureka().isEmpty()) {
                            applications.removeApplication(existingApp);
                        }
                    }
                }
            }
        }

        logger.debug("The total number of instances fetched by the delta processor : {}", deltaCount);
        this.getApplications().setVersion(delta.getVersion());
        this.getApplications().shuffleInstances(this.clientConfig.shouldFilterOnlyUpInstances());
        var3 = this.remoteRegionVsApps.values().iterator();

        while(var3.hasNext()) {
            Applications applications = (Applications)var3.next();
            applications.setVersion(delta.getVersion());
            applications.shuffleInstances(this.clientConfig.shouldFilterOnlyUpInstances());
        }

    }

    private void initScheduledTasks() {
        int renewalIntervalInSecs;
        int expBackOffBound;
        if (this.clientConfig.shouldFetchRegistry()) {
            renewalIntervalInSecs = this.clientConfig.getRegistryFetchIntervalSeconds();
            expBackOffBound = this.clientConfig.getCacheRefreshExecutorExponentialBackOffBound();
            this.cacheRefreshTask = new TimedSupervisorTask("cacheRefresh", this.scheduler, this.cacheRefreshExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.CacheRefreshThread());
            this.scheduler.schedule(this.cacheRefreshTask, (long)renewalIntervalInSecs, TimeUnit.SECONDS);
        }

        if (this.clientConfig.shouldRegisterWithEureka()) {
            renewalIntervalInSecs = this.instanceInfo.getLeaseInfo().getRenewalIntervalInSecs();
            expBackOffBound = this.clientConfig.getHeartbeatExecutorExponentialBackOffBound();
            logger.info("Starting heartbeat executor: renew interval is: {}", renewalIntervalInSecs);
            this.heartbeatTask = new TimedSupervisorTask("heartbeat", this.scheduler, this.heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.HeartbeatThread());
            this.scheduler.schedule(this.heartbeatTask, (long)renewalIntervalInSecs, TimeUnit.SECONDS);
            this.instanceInfoReplicator = new InstanceInfoReplicator(this, this.instanceInfo, this.clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2);
            this.statusChangeListener = new StatusChangeListener() {
                public String getId() {
                    return "statusChangeListener";
                }

                public void notify(StatusChangeEvent statusChangeEvent) {
                    if (InstanceStatus.DOWN != statusChangeEvent.getStatus() && InstanceStatus.DOWN != statusChangeEvent.getPreviousStatus()) {
                        DiscoveryClient.logger.info("Saw local status change event {}", statusChangeEvent);
                    } else {
                        DiscoveryClient.logger.warn("Saw local status change event {}", statusChangeEvent);
                    }

                    DiscoveryClient.this.instanceInfoReplicator.onDemandUpdate();
                }
            };
            if (this.clientConfig.shouldOnDemandUpdateStatusChange()) {
                this.applicationInfoManager.registerStatusChangeListener(this.statusChangeListener);
            }

            this.instanceInfoReplicator.start(this.clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());
        } else {
            logger.info("Not registering with Eureka server per configuration");
        }

    }

    private void cancelScheduledTasks() {
        if (this.instanceInfoReplicator != null) {
            this.instanceInfoReplicator.stop();
        }

        if (this.heartbeatExecutor != null) {
            this.heartbeatExecutor.shutdownNow();
        }

        if (this.cacheRefreshExecutor != null) {
            this.cacheRefreshExecutor.shutdownNow();
        }

        if (this.scheduler != null) {
            this.scheduler.shutdownNow();
        }

        if (this.cacheRefreshTask != null) {
            this.cacheRefreshTask.cancel();
        }

        if (this.heartbeatTask != null) {
            this.heartbeatTask.cancel();
        }

    }

    /** @deprecated */
    @Deprecated
    public List<String> getServiceUrlsFromDNS(String instanceZone, boolean preferSameZone) {
        return EndpointUtils.getServiceUrlsFromDNS(this.clientConfig, instanceZone, preferSameZone, this.urlRandomizer);
    }

    /** @deprecated */
    @Deprecated
    public List<String> getDiscoveryServiceUrls(String zone) {
        return EndpointUtils.getDiscoveryServiceUrls(this.clientConfig, zone, this.urlRandomizer);
    }

    /** @deprecated */
    @Deprecated
    public static Set<String> getEC2DiscoveryUrlsFromZone(String dnsName, DiscoveryUrlType type) {
        return EndpointUtils.getEC2DiscoveryUrlsFromZone(dnsName, type);
    }

    void refreshInstanceInfo() {
        this.applicationInfoManager.refreshDataCenterInfoIfRequired();
        this.applicationInfoManager.refreshLeaseInfoIfRequired();

        InstanceStatus status;
        try {
            status = this.getHealthCheckHandler().getStatus(this.instanceInfo.getStatus());
        } catch (Exception var3) {
            logger.warn("Exception from healthcheckHandler.getStatus, setting status to DOWN", var3);
            status = InstanceStatus.DOWN;
        }

        if (null != status) {
            this.applicationInfoManager.setInstanceStatus(status);
        }

    }

    @VisibleForTesting
    InstanceInfoReplicator getInstanceInfoReplicator() {
        return this.instanceInfoReplicator;
    }

    @VisibleForTesting
    InstanceInfo getInstanceInfo() {
        return this.instanceInfo;
    }

    public HealthCheckHandler getHealthCheckHandler() {
        HealthCheckHandler healthCheckHandler = (HealthCheckHandler)this.healthCheckHandlerRef.get();
        if (healthCheckHandler == null) {
            if (null != this.healthCheckHandlerProvider) {
                healthCheckHandler = (HealthCheckHandler)this.healthCheckHandlerProvider.get();
            } else if (null != this.healthCheckCallbackProvider) {
                healthCheckHandler = new HealthCheckCallbackToHandlerBridge((HealthCheckCallback)this.healthCheckCallbackProvider.get());
            }

            if (null == healthCheckHandler) {
                healthCheckHandler = new HealthCheckCallbackToHandlerBridge((HealthCheckCallback)null);
            }

            this.healthCheckHandlerRef.compareAndSet((Object)null, healthCheckHandler);
        }

        return (HealthCheckHandler)this.healthCheckHandlerRef.get();
    }

    @VisibleForTesting
    void refreshRegistry() {
        try {
            boolean isFetchingRemoteRegionRegistries = this.isFetchingRemoteRegionRegistries();
            boolean remoteRegionsModified = false;
            String latestRemoteRegions = this.clientConfig.fetchRegistryForRemoteRegions();
            if (null != latestRemoteRegions) {
                String currentRemoteRegions = (String)this.remoteRegionsToFetch.get();
                if (!latestRemoteRegions.equals(currentRemoteRegions)) {
                    synchronized(this.instanceRegionChecker.getAzToRegionMapper()) {
                        if (this.remoteRegionsToFetch.compareAndSet(currentRemoteRegions, latestRemoteRegions)) {
                            String[] remoteRegions = latestRemoteRegions.split(",");
                            this.remoteRegionsRef.set(remoteRegions);
                            this.instanceRegionChecker.getAzToRegionMapper().setRegionsToFetch(remoteRegions);
                            remoteRegionsModified = true;
                        } else {
                            logger.info("Remote regions to fetch modified concurrently, ignoring change from {} to {}", currentRemoteRegions, latestRemoteRegions);
                        }
                    }
                } else {
                    this.instanceRegionChecker.getAzToRegionMapper().refreshMapping();
                }
            }

            boolean success = this.fetchRegistry(remoteRegionsModified);
            if (success) {
                this.registrySize = ((Applications)this.localRegionApps.get()).size();
                this.lastSuccessfulRegistryFetchTimestamp = System.currentTimeMillis();
            }

            if (logger.isDebugEnabled()) {
                StringBuilder allAppsHashCodes = new StringBuilder();
                allAppsHashCodes.append("Local region apps hashcode: ");
                allAppsHashCodes.append(((Applications)this.localRegionApps.get()).getAppsHashCode());
                allAppsHashCodes.append(", is fetching remote regions? ");
                allAppsHashCodes.append(isFetchingRemoteRegionRegistries);
                Iterator var11 = this.remoteRegionVsApps.entrySet().iterator();

                while(var11.hasNext()) {
                    Entry<String, Applications> entry = (Entry)var11.next();
                    allAppsHashCodes.append(", Remote region: ");
                    allAppsHashCodes.append((String)entry.getKey());
                    allAppsHashCodes.append(" , apps hashcode: ");
                    allAppsHashCodes.append(((Applications)entry.getValue()).getAppsHashCode());
                }

                logger.debug("Completed cache refresh task for discovery. All Apps hash code is {} ", allAppsHashCodes);
            }
        } catch (Throwable var9) {
            logger.error("Cannot fetch registry from server", var9);
        }

    }

    private void fetchRegistryFromBackup() {
        try {
            BackupRegistry backupRegistryInstance = this.newBackupRegistryInstance();
            if (null == backupRegistryInstance) {
                backupRegistryInstance = (BackupRegistry)this.backupRegistryProvider.get();
            }

            if (null != backupRegistryInstance) {
                Applications apps = null;
                if (this.isFetchingRemoteRegionRegistries()) {
                    String remoteRegionsStr = (String)this.remoteRegionsToFetch.get();
                    if (null != remoteRegionsStr) {
                        apps = backupRegistryInstance.fetchRegistry(remoteRegionsStr.split(","));
                    }
                } else {
                    apps = backupRegistryInstance.fetchRegistry();
                }

                if (apps != null) {
                    Applications applications = this.filterAndShuffle(apps);
                    applications.setAppsHashCode(applications.getReconcileHashCode());
                    this.localRegionApps.set(applications);
                    this.logTotalInstances();
                    logger.info("Fetched registry successfully from the backup");
                }
            } else {
                logger.warn("No backup registry instance defined & unable to find any discovery servers.");
            }
        } catch (Throwable var4) {
            logger.warn("Cannot fetch applications from apps although backup registry was specified", var4);
        }

    }

    /** @deprecated */
    @Deprecated
    @Nullable
    protected BackupRegistry newBackupRegistryInstance() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        return null;
    }

    private Applications filterAndShuffle(Applications apps) {
        if (apps != null) {
            if (this.isFetchingRemoteRegionRegistries()) {
                Map<String, Applications> remoteRegionVsApps = new ConcurrentHashMap();
                apps.shuffleAndIndexInstances(remoteRegionVsApps, this.clientConfig, this.instanceRegionChecker);
                Iterator var3 = remoteRegionVsApps.values().iterator();

                while(var3.hasNext()) {
                    Applications applications = (Applications)var3.next();
                    applications.shuffleInstances(this.clientConfig.shouldFilterOnlyUpInstances());
                }

                this.remoteRegionVsApps = remoteRegionVsApps;
            } else {
                apps.shuffleInstances(this.clientConfig.shouldFilterOnlyUpInstances());
            }
        }

        return apps;
    }

    private boolean isFetchingRemoteRegionRegistries() {
        return null != this.remoteRegionsToFetch.get();
    }

    protected void onRemoteStatusChanged(InstanceStatus oldStatus, InstanceStatus newStatus) {
        this.fireEvent(new StatusChangeEvent(oldStatus, newStatus));
    }

    protected void onCacheRefreshed() {
        this.fireEvent(new CacheRefreshedEvent());
    }

    protected void fireEvent(EurekaEvent event) {
        Iterator var2 = this.eventListeners.iterator();

        while(var2.hasNext()) {
            EurekaEventListener listener = (EurekaEventListener)var2.next();

            try {
                listener.onEvent(event);
            } catch (Exception var5) {
                logger.info("Event {} throw an exception for listener {}", new Object[]{event, listener, var5.getMessage()});
            }
        }

    }

    /** @deprecated */
    @Deprecated
    public static String getZone(InstanceInfo myInfo) {
        String[] availZones = staticClientConfig.getAvailabilityZones(staticClientConfig.getRegion());
        return InstanceInfo.getZone(availZones, myInfo);
    }

    /** @deprecated */
    @Deprecated
    public static String getRegion() {
        String region = staticClientConfig.getRegion();
        if (region == null) {
            region = "default";
        }

        region = region.trim().toLowerCase();
        return region;
    }

    /** @deprecated */
    @Deprecated
    public static List<String> getEurekaServiceUrlsFromConfig(String instanceZone, boolean preferSameZone) {
        return EndpointUtils.getServiceUrlsFromConfig(staticClientConfig, instanceZone, preferSameZone);
    }

    public long getLastSuccessfulHeartbeatTimePeriod() {
        return this.lastSuccessfulHeartbeatTimestamp < 0L ? this.lastSuccessfulHeartbeatTimestamp : System.currentTimeMillis() - this.lastSuccessfulHeartbeatTimestamp;
    }

    public long getLastSuccessfulRegistryFetchTimePeriod() {
        return this.lastSuccessfulRegistryFetchTimestamp < 0L ? this.lastSuccessfulRegistryFetchTimestamp : System.currentTimeMillis() - this.lastSuccessfulRegistryFetchTimestamp;
    }

    @Monitor(
        name = "eurekaClient.registration.lastSuccessfulHeartbeatTimePeriod",
        description = "How much time has passed from last successful heartbeat",
        type = DataSourceType.GAUGE
    )
    private long getLastSuccessfulHeartbeatTimePeriodInternal() {
        long delay = this.clientConfig.shouldRegisterWithEureka() && !this.isShutdown.get() ? this.getLastSuccessfulHeartbeatTimePeriod() : 0L;
        this.heartbeatStalenessMonitor.update(this.computeStalenessMonitorDelay(delay));
        return delay;
    }

    @Monitor(
        name = "eurekaClient.registry.lastSuccessfulRegistryFetchTimePeriod",
        description = "How much time has passed from last successful local registry update",
        type = DataSourceType.GAUGE
    )
    private long getLastSuccessfulRegistryFetchTimePeriodInternal() {
        long delay = this.clientConfig.shouldFetchRegistry() && !this.isShutdown.get() ? this.getLastSuccessfulRegistryFetchTimePeriod() : 0L;
        this.registryStalenessMonitor.update(this.computeStalenessMonitorDelay(delay));
        return delay;
    }

    @Monitor(
        name = "eurekaClient.registry.localRegistrySize",
        description = "Count of instances in the local registry",
        type = DataSourceType.GAUGE
    )
    public int localRegistrySize() {
        return this.registrySize;
    }

    private long computeStalenessMonitorDelay(long delay) {
        return delay < 0L ? System.currentTimeMillis() - this.initTimestampMs : delay;
    }

    class CacheRefreshThread implements Runnable {
        CacheRefreshThread() {
        }

        public void run() {
            DiscoveryClient.this.refreshRegistry();
        }
    }

    private class HeartbeatThread implements Runnable {
        private HeartbeatThread() {
        }

        public void run() {
            if (DiscoveryClient.this.renew()) {
                DiscoveryClient.this.lastSuccessfulHeartbeatTimestamp = System.currentTimeMillis();
            }

        }
    }

    public static class DiscoveryClientOptionalArgs extends Jersey1DiscoveryClientOptionalArgs {
        public DiscoveryClientOptionalArgs() {
        }
    }

    private static final class EurekaTransport {
        private ClosableResolver bootstrapResolver;
        private TransportClientFactory transportClientFactory;
        private EurekaHttpClient registrationClient;
        private EurekaHttpClientFactory registrationClientFactory;
        private EurekaHttpClient queryClient;
        private EurekaHttpClientFactory queryClientFactory;

        private EurekaTransport() {
        }

        void shutdown() {
            if (this.registrationClientFactory != null) {
                this.registrationClientFactory.shutdown();
            }

            if (this.queryClientFactory != null) {
                this.queryClientFactory.shutdown();
            }

            if (this.registrationClient != null) {
                this.registrationClient.shutdown();
            }

            if (this.queryClient != null) {
                this.queryClient.shutdown();
            }

            if (this.transportClientFactory != null) {
                this.transportClientFactory.shutdown();
            }

            if (this.bootstrapResolver != null) {
                this.bootstrapResolver.shutdown();
            }

        }
    }
}

查看private final ApplicationInfoManager applicationInfoManager(应用信息管理器)

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.appinfo;

import com.netflix.appinfo.AmazonInfo.MetaDataKey;
import com.netflix.appinfo.InstanceInfo.Builder;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
import com.netflix.discovery.StatusChangeEvent;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class ApplicationInfoManager {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationInfoManager.class);
    private static final ApplicationInfoManager.InstanceStatusMapper NO_OP_MAPPER = new ApplicationInfoManager.InstanceStatusMapper() {
        public InstanceStatus map(InstanceStatus prev) {
            return prev;
        }
    };
    private static ApplicationInfoManager instance = new ApplicationInfoManager((EurekaInstanceConfig)null, (InstanceInfo)null, (ApplicationInfoManager.OptionalArgs)null);
    protected final Map<String, ApplicationInfoManager.StatusChangeListener> listeners;
    private final ApplicationInfoManager.InstanceStatusMapper instanceStatusMapper;
    private InstanceInfo instanceInfo;
    private EurekaInstanceConfig config;

    @Inject
    public ApplicationInfoManager(EurekaInstanceConfig config, InstanceInfo instanceInfo, ApplicationInfoManager.OptionalArgs optionalArgs) {
        this.config = config;
        this.instanceInfo = instanceInfo;
        this.listeners = new ConcurrentHashMap();
        if (optionalArgs != null) {
            this.instanceStatusMapper = optionalArgs.getInstanceStatusMapper();
        } else {
            this.instanceStatusMapper = NO_OP_MAPPER;
        }

        instance = this;
    }

    public ApplicationInfoManager(EurekaInstanceConfig config, ApplicationInfoManager.OptionalArgs optionalArgs) {
        this(config, (new EurekaConfigBasedInstanceInfoProvider(config)).get(), optionalArgs);
    }

    public ApplicationInfoManager(EurekaInstanceConfig config, InstanceInfo instanceInfo) {
        this(config, instanceInfo, (ApplicationInfoManager.OptionalArgs)null);
    }

    /** @deprecated */
    @Deprecated
    public ApplicationInfoManager(EurekaInstanceConfig config) {
        this(config, (ApplicationInfoManager.OptionalArgs)null);
    }

    /** @deprecated */
    @Deprecated
    public static ApplicationInfoManager getInstance() {
        return instance;
    }

    public void initComponent(EurekaInstanceConfig config) {
        try {
            this.config = config;
            this.instanceInfo = (new EurekaConfigBasedInstanceInfoProvider(config)).get();
        } catch (Throwable var3) {
            throw new RuntimeException("Failed to initialize ApplicationInfoManager", var3);
        }
    }

    public InstanceInfo getInfo() {
        return this.instanceInfo;
    }

    public EurekaInstanceConfig getEurekaInstanceConfig() {
        return this.config;
    }

    public void registerAppMetadata(Map<String, String> appMetadata) {
        this.instanceInfo.registerRuntimeMetadata(appMetadata);
    }

    public synchronized void setInstanceStatus(InstanceStatus status) {
        InstanceStatus next = this.instanceStatusMapper.map(status);
        if (next != null) {
            InstanceStatus prev = this.instanceInfo.setStatus(next);
            if (prev != null) {
                Iterator var4 = this.listeners.values().iterator();

                while(var4.hasNext()) {
                    ApplicationInfoManager.StatusChangeListener listener = (ApplicationInfoManager.StatusChangeListener)var4.next();

                    try {
                        listener.notify(new StatusChangeEvent(prev, next));
                    } catch (Exception var7) {
                        logger.warn("failed to notify listener: {}", listener.getId(), var7);
                    }
                }
            }

        }
    }

    public void registerStatusChangeListener(ApplicationInfoManager.StatusChangeListener listener) {
        this.listeners.put(listener.getId(), listener);
    }

    public void unregisterStatusChangeListener(String listenerId) {
        this.listeners.remove(listenerId);
    }

    public void refreshDataCenterInfoIfRequired() {
        String existingAddress = this.instanceInfo.getHostName();
        String existingSpotInstanceAction = null;
        if (this.instanceInfo.getDataCenterInfo() instanceof AmazonInfo) {
            existingSpotInstanceAction = ((AmazonInfo)this.instanceInfo.getDataCenterInfo()).get(MetaDataKey.spotInstanceAction);
        }

        String newAddress;
        if (this.config instanceof RefreshableInstanceConfig) {
            newAddress = ((RefreshableInstanceConfig)this.config).resolveDefaultAddress(true);
        } else {
            newAddress = this.config.getHostName(true);
        }

        String newIp = this.config.getIpAddress();
        if (newAddress != null && !newAddress.equals(existingAddress)) {
            logger.warn("The address changed from : {} => {}", existingAddress, newAddress);
            this.updateInstanceInfo(newAddress, newIp);
        }

        if (this.config.getDataCenterInfo() instanceof AmazonInfo) {
            String newSpotInstanceAction = ((AmazonInfo)this.config.getDataCenterInfo()).get(MetaDataKey.spotInstanceAction);
            if (newSpotInstanceAction != null && !newSpotInstanceAction.equals(existingSpotInstanceAction)) {
                logger.info(String.format("The spot instance termination action changed from: %s => %s", existingSpotInstanceAction, newSpotInstanceAction));
                this.updateInstanceInfo((String)null, (String)null);
            }
        }

    }

    private void updateInstanceInfo(String newAddress, String newIp) {
        Builder builder = new Builder(this.instanceInfo);
        if (newAddress != null) {
            builder.setHostName(newAddress);
        }

        if (newIp != null) {
            builder.setIPAddr(newIp);
        }

        builder.setDataCenterInfo(this.config.getDataCenterInfo());
        this.instanceInfo.setIsDirty();
    }

    public void refreshLeaseInfoIfRequired() {
        LeaseInfo leaseInfo = this.instanceInfo.getLeaseInfo();
        if (leaseInfo != null) {
            int currentLeaseDuration = this.config.getLeaseExpirationDurationInSeconds();
            int currentLeaseRenewal = this.config.getLeaseRenewalIntervalInSeconds();
            if (leaseInfo.getDurationInSecs() != currentLeaseDuration || leaseInfo.getRenewalIntervalInSecs() != currentLeaseRenewal) {
                LeaseInfo newLeaseInfo = com.netflix.appinfo.LeaseInfo.Builder.newBuilder().setRenewalIntervalInSecs(currentLeaseRenewal).setDurationInSecs(currentLeaseDuration).build();
                this.instanceInfo.setLeaseInfo(newLeaseInfo);
                this.instanceInfo.setIsDirty();
            }

        }
    }

    public interface InstanceStatusMapper {
        InstanceStatus map(InstanceStatus var1);
    }

    public interface StatusChangeListener {
        String getId();

        void notify(StatusChangeEvent var1);
    }

    public static class OptionalArgs {
        private ApplicationInfoManager.InstanceStatusMapper instanceStatusMapper;

        public OptionalArgs() {
        }

        @com.google.inject.Inject(
            optional = true
        )
        public void setInstanceStatusMapper(ApplicationInfoManager.InstanceStatusMapper instanceStatusMapper) {
            this.instanceStatusMapper = instanceStatusMapper;
        }

        ApplicationInfoManager.InstanceStatusMapper getInstanceStatusMapper() {
            return this.instanceStatusMapper == null ? ApplicationInfoManager.NO_OP_MAPPER : this.instanceStatusMapper;
        }
    }
}

发现此类的构造函数总有两个属性

  • private InstanceInfo instanceInfo
  • private EurekaInstanceConfig config

服务实例的信息类InstanceInfo和服务实例配置信息类EurekaInstanceConfig

看InstanceInfo.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.appinfo;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonRootName;
import com.google.inject.ProvidedBy;
import com.netflix.appinfo.AmazonInfo.MetaDataKey;
import com.netflix.appinfo.DataCenterInfo.Name;
import com.netflix.appinfo.providers.Archaius1VipAddressResolver;
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
import com.netflix.appinfo.providers.VipAddressResolver;
import com.netflix.discovery.converters.Auto;
import com.netflix.discovery.provider.Serializer;
import com.netflix.discovery.util.StringCache;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@ProvidedBy(EurekaConfigBasedInstanceInfoProvider.class)
@Serializer("com.netflix.discovery.converters.EntityBodyConverter")
@XStreamAlias("instance")
@JsonRootName("instance")
public class InstanceInfo {
    private static final String VERSION_UNKNOWN = "unknown";
    private static final Logger logger = LoggerFactory.getLogger(InstanceInfo.class);
    public static final int DEFAULT_PORT = 7001;
    public static final int DEFAULT_SECURE_PORT = 7002;
    public static final int DEFAULT_COUNTRY_ID = 1;
    private volatile String instanceId;
    private volatile String appName;
    @Auto
    private volatile String appGroupName;
    private volatile String ipAddr;
    private static final String SID_DEFAULT = "na";
    /** @deprecated */
    @Deprecated
    private volatile String sid;
    private volatile int port;
    private volatile int securePort;
    @Auto
    private volatile String homePageUrl;
    @Auto
    private volatile String statusPageUrl;
    @Auto
    private volatile String healthCheckUrl;
    @Auto
    private volatile String secureHealthCheckUrl;
    @Auto
    private volatile String vipAddress;
    @Auto
    private volatile String secureVipAddress;
    @XStreamOmitField
    private String statusPageRelativeUrl;
    @XStreamOmitField
    private String statusPageExplicitUrl;
    @XStreamOmitField
    private String healthCheckRelativeUrl;
    @XStreamOmitField
    private String healthCheckSecureExplicitUrl;
    @XStreamOmitField
    private String vipAddressUnresolved;
    @XStreamOmitField
    private String secureVipAddressUnresolved;
    @XStreamOmitField
    private String healthCheckExplicitUrl;
    /** @deprecated */
    @Deprecated
    private volatile int countryId;
    private volatile boolean isSecurePortEnabled;
    private volatile boolean isUnsecurePortEnabled;
    private volatile DataCenterInfo dataCenterInfo;
    private volatile String hostName;
    private volatile InstanceInfo.InstanceStatus status;
    private volatile InstanceInfo.InstanceStatus overriddenStatus;
    @XStreamOmitField
    private volatile boolean isInstanceInfoDirty;
    private volatile LeaseInfo leaseInfo;
    @Auto
    private volatile Boolean isCoordinatingDiscoveryServer;
    @XStreamAlias("metadata")
    private volatile Map<String, String> metadata;
    @Auto
    private volatile Long lastUpdatedTimestamp;
    @Auto
    private volatile Long lastDirtyTimestamp;
    @Auto
    private volatile InstanceInfo.ActionType actionType;
    @Auto
    private volatile String asgName;
    private String version;

    private InstanceInfo() {
        this.sid = "na";
        this.port = 7001;
        this.securePort = 7002;
        this.countryId = 1;
        this.isSecurePortEnabled = false;
        this.isUnsecurePortEnabled = true;
        this.status = InstanceInfo.InstanceStatus.UP;
        this.overriddenStatus = InstanceInfo.InstanceStatus.UNKNOWN;
        this.isInstanceInfoDirty = false;
        this.isCoordinatingDiscoveryServer = Boolean.FALSE;
        this.version = "unknown";
        this.metadata = new ConcurrentHashMap();
        this.lastUpdatedTimestamp = System.currentTimeMillis();
        this.lastDirtyTimestamp = this.lastUpdatedTimestamp;
    }

    @JsonCreator
    public InstanceInfo(@JsonProperty("instanceId") String instanceId, @JsonProperty("app") String appName, @JsonProperty("appGroupName") String appGroupName, @JsonProperty("ipAddr") String ipAddr, @JsonProperty("sid") String sid, @JsonProperty("port") InstanceInfo.PortWrapper port, @JsonProperty("securePort") InstanceInfo.PortWrapper securePort, @JsonProperty("homePageUrl") String homePageUrl, @JsonProperty("statusPageUrl") String statusPageUrl, @JsonProperty("healthCheckUrl") String healthCheckUrl, @JsonProperty("secureHealthCheckUrl") String secureHealthCheckUrl, @JsonProperty("vipAddress") String vipAddress, @JsonProperty("secureVipAddress") String secureVipAddress, @JsonProperty("countryId") int countryId, @JsonProperty("dataCenterInfo") DataCenterInfo dataCenterInfo, @JsonProperty("hostName") String hostName, @JsonProperty("status") InstanceInfo.InstanceStatus status, @JsonProperty("overriddenstatus") InstanceInfo.InstanceStatus overriddenStatus, @JsonProperty("overriddenStatus") InstanceInfo.InstanceStatus overriddenStatusAlt, @JsonProperty("leaseInfo") LeaseInfo leaseInfo, @JsonProperty("isCoordinatingDiscoveryServer") Boolean isCoordinatingDiscoveryServer, @JsonProperty("metadata") HashMap<String, String> metadata, @JsonProperty("lastUpdatedTimestamp") Long lastUpdatedTimestamp, @JsonProperty("lastDirtyTimestamp") Long lastDirtyTimestamp, @JsonProperty("actionType") InstanceInfo.ActionType actionType, @JsonProperty("asgName") String asgName) {
        this.sid = "na";
        this.port = 7001;
        this.securePort = 7002;
        this.countryId = 1;
        this.isSecurePortEnabled = false;
        this.isUnsecurePortEnabled = true;
        this.status = InstanceInfo.InstanceStatus.UP;
        this.overriddenStatus = InstanceInfo.InstanceStatus.UNKNOWN;
        this.isInstanceInfoDirty = false;
        this.isCoordinatingDiscoveryServer = Boolean.FALSE;
        this.version = "unknown";
        this.instanceId = instanceId;
        this.sid = sid;
        this.appName = StringCache.intern(appName);
        this.appGroupName = StringCache.intern(appGroupName);
        this.ipAddr = ipAddr;
        this.port = port == null ? 0 : port.getPort();
        this.isUnsecurePortEnabled = port != null && port.isEnabled();
        this.securePort = securePort == null ? 0 : securePort.getPort();
        this.isSecurePortEnabled = securePort != null && securePort.isEnabled();
        this.homePageUrl = homePageUrl;
        this.statusPageUrl = statusPageUrl;
        this.healthCheckUrl = healthCheckUrl;
        this.secureHealthCheckUrl = secureHealthCheckUrl;
        this.vipAddress = StringCache.intern(vipAddress);
        this.secureVipAddress = StringCache.intern(secureVipAddress);
        this.countryId = countryId;
        this.dataCenterInfo = dataCenterInfo;
        this.hostName = hostName;
        this.status = status;
        this.overriddenStatus = overriddenStatus == null ? overriddenStatusAlt : overriddenStatus;
        this.leaseInfo = leaseInfo;
        this.isCoordinatingDiscoveryServer = isCoordinatingDiscoveryServer;
        this.lastUpdatedTimestamp = lastUpdatedTimestamp;
        this.lastDirtyTimestamp = lastDirtyTimestamp;
        this.actionType = actionType;
        this.asgName = StringCache.intern(asgName);
        if (metadata == null) {
            this.metadata = Collections.emptyMap();
        } else if (metadata.size() == 1) {
            this.metadata = this.removeMetadataMapLegacyValues(metadata);
        } else {
            this.metadata = metadata;
        }

        if (sid == null) {
            this.sid = "na";
        }

    }

    public String toString() {
        return "InstanceInfo [instanceId = " + this.instanceId + ", appName = " + this.appName + ", hostName = " + this.hostName + ", status = " + this.status + ", ipAddr = " + this.ipAddr + ", port = " + this.port + ", securePort = " + this.securePort + ", dataCenterInfo = " + this.dataCenterInfo;
    }

    private Map<String, String> removeMetadataMapLegacyValues(Map<String, String> metadata) {
        if ("java.util.Collections$EmptyMap".equals(metadata.get("@class"))) {
            metadata.remove("@class");
        } else if ("java.util.Collections$EmptyMap".equals(metadata.get("class"))) {
            metadata.remove("class");
        }

        return metadata;
    }

    public InstanceInfo(InstanceInfo ii) {
        this.sid = "na";
        this.port = 7001;
        this.securePort = 7002;
        this.countryId = 1;
        this.isSecurePortEnabled = false;
        this.isUnsecurePortEnabled = true;
        this.status = InstanceInfo.InstanceStatus.UP;
        this.overriddenStatus = InstanceInfo.InstanceStatus.UNKNOWN;
        this.isInstanceInfoDirty = false;
        this.isCoordinatingDiscoveryServer = Boolean.FALSE;
        this.version = "unknown";
        this.instanceId = ii.instanceId;
        this.appName = ii.appName;
        this.appGroupName = ii.appGroupName;
        this.ipAddr = ii.ipAddr;
        this.sid = ii.sid;
        this.port = ii.port;
        this.securePort = ii.securePort;
        this.homePageUrl = ii.homePageUrl;
        this.statusPageUrl = ii.statusPageUrl;
        this.healthCheckUrl = ii.healthCheckUrl;
        this.secureHealthCheckUrl = ii.secureHealthCheckUrl;
        this.vipAddress = ii.vipAddress;
        this.secureVipAddress = ii.secureVipAddress;
        this.statusPageRelativeUrl = ii.statusPageRelativeUrl;
        this.statusPageExplicitUrl = ii.statusPageExplicitUrl;
        this.healthCheckRelativeUrl = ii.healthCheckRelativeUrl;
        this.healthCheckSecureExplicitUrl = ii.healthCheckSecureExplicitUrl;
        this.vipAddressUnresolved = ii.vipAddressUnresolved;
        this.secureVipAddressUnresolved = ii.secureVipAddressUnresolved;
        this.healthCheckExplicitUrl = ii.healthCheckExplicitUrl;
        this.countryId = ii.countryId;
        this.isSecurePortEnabled = ii.isSecurePortEnabled;
        this.isUnsecurePortEnabled = ii.isUnsecurePortEnabled;
        this.dataCenterInfo = ii.dataCenterInfo;
        this.hostName = ii.hostName;
        this.status = ii.status;
        this.overriddenStatus = ii.overriddenStatus;
        this.isInstanceInfoDirty = ii.isInstanceInfoDirty;
        this.leaseInfo = ii.leaseInfo;
        this.isCoordinatingDiscoveryServer = ii.isCoordinatingDiscoveryServer;
        this.metadata = ii.metadata;
        this.lastUpdatedTimestamp = ii.lastUpdatedTimestamp;
        this.lastDirtyTimestamp = ii.lastDirtyTimestamp;
        this.actionType = ii.actionType;
        this.asgName = ii.asgName;
        this.version = ii.version;
    }

    public int hashCode() {
        String id = this.getId();
        return id == null ? 31 : id.hashCode() + 31;
    }

    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        } else if (obj == null) {
            return false;
        } else if (this.getClass() != obj.getClass()) {
            return false;
        } else {
            InstanceInfo other = (InstanceInfo)obj;
            String id = this.getId();
            if (id == null) {
                if (other.getId() != null) {
                    return false;
                }
            } else if (!id.equals(other.getId())) {
                return false;
            }

            return true;
        }
    }

    public String getInstanceId() {
        return this.instanceId;
    }

    @JsonProperty("app")
    public String getAppName() {
        return this.appName;
    }

    public String getAppGroupName() {
        return this.appGroupName;
    }

    public String getHostName() {
        return this.hostName;
    }

    /** @deprecated */
    @Deprecated
    public void setSID(String sid) {
        this.sid = sid;
        this.setIsDirty();
    }

    /** @deprecated */
    @JsonProperty("sid")
    @Deprecated
    public String getSID() {
        return this.sid;
    }

    @JsonIgnore
    public String getId() {
        if (this.instanceId != null && !this.instanceId.isEmpty()) {
            return this.instanceId;
        } else {
            if (this.dataCenterInfo instanceof UniqueIdentifier) {
                String uniqueId = ((UniqueIdentifier)this.dataCenterInfo).getId();
                if (uniqueId != null && !uniqueId.isEmpty()) {
                    return uniqueId;
                }
            }

            return this.hostName;
        }
    }

    @JsonProperty("ipAddr")
    public String getIPAddr() {
        return this.ipAddr;
    }

    @JsonIgnore
    public int getPort() {
        return this.port;
    }

    public InstanceInfo.InstanceStatus getStatus() {
        return this.status;
    }

    public InstanceInfo.InstanceStatus getOverriddenStatus() {
        return this.overriddenStatus;
    }

    public DataCenterInfo getDataCenterInfo() {
        return this.dataCenterInfo;
    }

    public LeaseInfo getLeaseInfo() {
        return this.leaseInfo;
    }

    public void setLeaseInfo(LeaseInfo info) {
        this.leaseInfo = info;
    }

    public Map<String, String> getMetadata() {
        return this.metadata;
    }

    /** @deprecated */
    @Deprecated
    public int getCountryId() {
        return this.countryId;
    }

    @JsonIgnore
    public int getSecurePort() {
        return this.securePort;
    }

    @JsonIgnore
    public boolean isPortEnabled(InstanceInfo.PortType type) {
        return type == InstanceInfo.PortType.SECURE ? this.isSecurePortEnabled : this.isUnsecurePortEnabled;
    }

    public long getLastUpdatedTimestamp() {
        return this.lastUpdatedTimestamp;
    }

    public void setLastUpdatedTimestamp() {
        this.lastUpdatedTimestamp = System.currentTimeMillis();
    }

    public String getHomePageUrl() {
        return this.homePageUrl;
    }

    public String getStatusPageUrl() {
        return this.statusPageUrl;
    }

    @JsonIgnore
    public Set<String> getHealthCheckUrls() {
        Set<String> healthCheckUrlSet = new LinkedHashSet();
        if (this.isUnsecurePortEnabled && this.healthCheckUrl != null && !this.healthCheckUrl.isEmpty()) {
            healthCheckUrlSet.add(this.healthCheckUrl);
        }

        if (this.isSecurePortEnabled && this.secureHealthCheckUrl != null && !this.secureHealthCheckUrl.isEmpty()) {
            healthCheckUrlSet.add(this.secureHealthCheckUrl);
        }

        return healthCheckUrlSet;
    }

    public String getHealthCheckUrl() {
        return this.healthCheckUrl;
    }

    public String getSecureHealthCheckUrl() {
        return this.secureHealthCheckUrl;
    }

    @JsonProperty("vipAddress")
    public String getVIPAddress() {
        return this.vipAddress;
    }

    public String getSecureVipAddress() {
        return this.secureVipAddress;
    }

    public Long getLastDirtyTimestamp() {
        return this.lastDirtyTimestamp;
    }

    public void setLastDirtyTimestamp(Long lastDirtyTimestamp) {
        this.lastDirtyTimestamp = lastDirtyTimestamp;
    }

    public synchronized InstanceInfo.InstanceStatus setStatus(InstanceInfo.InstanceStatus status) {
        if (this.status != status) {
            InstanceInfo.InstanceStatus prev = this.status;
            this.status = status;
            this.setIsDirty();
            return prev;
        } else {
            return null;
        }
    }

    public synchronized void setStatusWithoutDirty(InstanceInfo.InstanceStatus status) {
        if (this.status != status) {
            this.status = status;
        }

    }

    public synchronized void setOverriddenStatus(InstanceInfo.InstanceStatus status) {
        if (this.overriddenStatus != status) {
            this.overriddenStatus = status;
        }

    }

    @JsonIgnore
    public boolean isDirty() {
        return this.isInstanceInfoDirty;
    }

    public synchronized Long isDirtyWithTime() {
        return this.isInstanceInfoDirty ? this.lastDirtyTimestamp : null;
    }

    /** @deprecated */
    @Deprecated
    public synchronized void setIsDirty(boolean isDirty) {
        if (isDirty) {
            this.setIsDirty();
        } else {
            this.isInstanceInfoDirty = false;
        }

    }

    public synchronized void setIsDirty() {
        this.isInstanceInfoDirty = true;
        this.lastDirtyTimestamp = System.currentTimeMillis();
    }

    public synchronized long setIsDirtyWithTime() {
        this.setIsDirty();
        return this.lastDirtyTimestamp;
    }

    public synchronized void unsetIsDirty(long unsetDirtyTimestamp) {
        if (this.lastDirtyTimestamp <= unsetDirtyTimestamp) {
            this.isInstanceInfoDirty = false;
        }

    }

    public void setIsCoordinatingDiscoveryServer() {
        String instanceId = this.getId();
        if (instanceId != null && instanceId.equals(ApplicationInfoManager.getInstance().getInfo().getId())) {
            this.isCoordinatingDiscoveryServer = Boolean.TRUE;
        } else {
            this.isCoordinatingDiscoveryServer = Boolean.FALSE;
        }

    }

    @JsonProperty("isCoordinatingDiscoveryServer")
    public Boolean isCoordinatingDiscoveryServer() {
        return this.isCoordinatingDiscoveryServer;
    }

    public InstanceInfo.ActionType getActionType() {
        return this.actionType;
    }

    public void setActionType(InstanceInfo.ActionType actionType) {
        this.actionType = actionType;
    }

    @JsonProperty("asgName")
    public String getASGName() {
        return this.asgName;
    }

    /** @deprecated */
    @Deprecated
    @JsonIgnore
    public String getVersion() {
        return this.version;
    }

    synchronized void registerRuntimeMetadata(Map<String, String> runtimeMetadata) {
        this.metadata.putAll(runtimeMetadata);
        this.setIsDirty();
    }

    public static String getZone(String[] availZones, InstanceInfo myInfo) {
        String instanceZone = availZones != null && availZones.length != 0 ? availZones[0] : "default";
        if (myInfo != null && myInfo.getDataCenterInfo().getName() == Name.Amazon) {
            String awsInstanceZone = ((AmazonInfo)myInfo.getDataCenterInfo()).get(MetaDataKey.availabilityZone);
            if (awsInstanceZone != null) {
                instanceZone = awsInstanceZone;
            }
        }

        return instanceZone;
    }

    public static enum ActionType {
        ADDED,
        MODIFIED,
        DELETED;

        private ActionType() {
        }
    }

    public static final class Builder {
        private static final String COLON = ":";
        private static final String HTTPS_PROTOCOL = "https://";
        private static final String HTTP_PROTOCOL = "http://";
        private final Function<String, String> intern;
        @XStreamOmitField
        private InstanceInfo result;
        @XStreamOmitField
        private final VipAddressResolver vipAddressResolver;
        private String namespace;

        private Builder(InstanceInfo result, VipAddressResolver vipAddressResolver, Function<String, String> intern) {
            this.vipAddressResolver = vipAddressResolver;
            this.result = result;
            this.intern = intern != null ? intern : StringCache::intern;
        }

        public Builder(InstanceInfo instanceInfo) {
            this(instanceInfo, InstanceInfo.Builder.LazyHolder.DEFAULT_VIP_ADDRESS_RESOLVER, (Function)null);
        }

        public static InstanceInfo.Builder newBuilder() {
            return new InstanceInfo.Builder(new InstanceInfo(), InstanceInfo.Builder.LazyHolder.DEFAULT_VIP_ADDRESS_RESOLVER, (Function)null);
        }

        public static InstanceInfo.Builder newBuilder(Function<String, String> intern) {
            return new InstanceInfo.Builder(new InstanceInfo(), InstanceInfo.Builder.LazyHolder.DEFAULT_VIP_ADDRESS_RESOLVER, intern);
        }

        public static InstanceInfo.Builder newBuilder(VipAddressResolver vipAddressResolver) {
            return new InstanceInfo.Builder(new InstanceInfo(), vipAddressResolver, (Function)null);
        }

        public InstanceInfo.Builder setInstanceId(String instanceId) {
            this.result.instanceId = instanceId;
            return this;
        }

        public InstanceInfo.Builder setAppName(String appName) {
            this.result.appName = (String)this.intern.apply(appName.toUpperCase(Locale.ROOT));
            return this;
        }

        public InstanceInfo.Builder setAppNameForDeser(String appName) {
            this.result.appName = appName;
            return this;
        }

        public InstanceInfo.Builder setAppGroupName(String appGroupName) {
            if (appGroupName != null) {
                this.result.appGroupName = (String)this.intern.apply(appGroupName.toUpperCase(Locale.ROOT));
            } else {
                this.result.appGroupName = null;
            }

            return this;
        }

        public InstanceInfo.Builder setAppGroupNameForDeser(String appGroupName) {
            this.result.appGroupName = appGroupName;
            return this;
        }

        public InstanceInfo.Builder setHostName(String hostName) {
            if (hostName != null && !hostName.isEmpty()) {
                String existingHostName = this.result.hostName;
                this.result.hostName = hostName;
                if (existingHostName != null && !hostName.equals(existingHostName)) {
                    this.refreshStatusPageUrl().refreshHealthCheckUrl().refreshVIPAddress().refreshSecureVIPAddress();
                }

                return this;
            } else {
                InstanceInfo.logger.warn("Passed in hostname is blank, not setting it");
                return this;
            }
        }

        public InstanceInfo.Builder setStatus(InstanceInfo.InstanceStatus status) {
            this.result.status = status;
            return this;
        }

        public InstanceInfo.Builder setOverriddenStatus(InstanceInfo.InstanceStatus status) {
            this.result.overriddenStatus = status;
            return this;
        }

        public InstanceInfo.Builder setIPAddr(String ip) {
            this.result.ipAddr = ip;
            return this;
        }

        /** @deprecated */
        @Deprecated
        public InstanceInfo.Builder setSID(String sid) {
            this.result.sid = sid;
            return this;
        }

        public InstanceInfo.Builder setPort(int port) {
            this.result.port = port;
            return this;
        }

        public InstanceInfo.Builder setSecurePort(int port) {
            this.result.securePort = port;
            return this;
        }

        public InstanceInfo.Builder enablePort(InstanceInfo.PortType type, boolean isEnabled) {
            if (type == InstanceInfo.PortType.SECURE) {
                this.result.isSecurePortEnabled = isEnabled;
            } else {
                this.result.isUnsecurePortEnabled = isEnabled;
            }

            return this;
        }

        /** @deprecated */
        @Deprecated
        public InstanceInfo.Builder setCountryId(int id) {
            this.result.countryId = id;
            return this;
        }

        public InstanceInfo.Builder setHomePageUrl(String relativeUrl, String explicitUrl) {
            String hostNameInterpolationExpression = "${" + this.namespace + "hostname}";
            if (explicitUrl != null) {
                this.result.homePageUrl = explicitUrl.replace(hostNameInterpolationExpression, this.result.hostName);
            } else if (relativeUrl != null) {
                this.result.homePageUrl = "http://" + this.result.hostName + ":" + this.result.port + relativeUrl;
            }

            return this;
        }

        public InstanceInfo.Builder setHomePageUrlForDeser(String homePageUrl) {
            this.result.homePageUrl = homePageUrl;
            return this;
        }

        public InstanceInfo.Builder setStatusPageUrl(String relativeUrl, String explicitUrl) {
            String hostNameInterpolationExpression = "${" + this.namespace + "hostname}";
            this.result.statusPageRelativeUrl = relativeUrl;
            this.result.statusPageExplicitUrl = explicitUrl;
            if (explicitUrl != null) {
                this.result.statusPageUrl = explicitUrl.replace(hostNameInterpolationExpression, this.result.hostName);
            } else if (relativeUrl != null) {
                this.result.statusPageUrl = "http://" + this.result.hostName + ":" + this.result.port + relativeUrl;
            }

            return this;
        }

        public InstanceInfo.Builder setStatusPageUrlForDeser(String statusPageUrl) {
            this.result.statusPageUrl = statusPageUrl;
            return this;
        }

        public InstanceInfo.Builder setHealthCheckUrls(String relativeUrl, String explicitUrl, String secureExplicitUrl) {
            String hostNameInterpolationExpression = "${" + this.namespace + "hostname}";
            this.result.healthCheckRelativeUrl = relativeUrl;
            this.result.healthCheckExplicitUrl = explicitUrl;
            this.result.healthCheckSecureExplicitUrl = secureExplicitUrl;
            if (explicitUrl != null) {
                this.result.healthCheckUrl = explicitUrl.replace(hostNameInterpolationExpression, this.result.hostName);
            } else if (this.result.isUnsecurePortEnabled) {
                this.result.healthCheckUrl = "http://" + this.result.hostName + ":" + this.result.port + relativeUrl;
            }

            if (secureExplicitUrl != null) {
                this.result.secureHealthCheckUrl = secureExplicitUrl.replace(hostNameInterpolationExpression, this.result.hostName);
            } else if (this.result.isSecurePortEnabled) {
                this.result.secureHealthCheckUrl = "https://" + this.result.hostName + ":" + this.result.securePort + relativeUrl;
            }

            return this;
        }

        public InstanceInfo.Builder setHealthCheckUrlsForDeser(String healthCheckUrl, String secureHealthCheckUrl) {
            if (healthCheckUrl != null) {
                this.result.healthCheckUrl = healthCheckUrl;
            }

            if (secureHealthCheckUrl != null) {
                this.result.secureHealthCheckUrl = secureHealthCheckUrl;
            }

            return this;
        }

        public InstanceInfo.Builder setVIPAddress(String vipAddress) {
            this.result.vipAddressUnresolved = (String)this.intern.apply(vipAddress);
            this.result.vipAddress = (String)this.intern.apply(this.vipAddressResolver.resolveDeploymentContextBasedVipAddresses(vipAddress));
            return this;
        }

        public InstanceInfo.Builder setVIPAddressDeser(String vipAddress) {
            this.result.vipAddress = (String)this.intern.apply(vipAddress);
            return this;
        }

        public InstanceInfo.Builder setSecureVIPAddress(String secureVIPAddress) {
            this.result.secureVipAddressUnresolved = (String)this.intern.apply(secureVIPAddress);
            this.result.secureVipAddress = (String)this.intern.apply(this.vipAddressResolver.resolveDeploymentContextBasedVipAddresses(secureVIPAddress));
            return this;
        }

        public InstanceInfo.Builder setSecureVIPAddressDeser(String secureVIPAddress) {
            this.result.secureVipAddress = (String)this.intern.apply(secureVIPAddress);
            return this;
        }

        public InstanceInfo.Builder setDataCenterInfo(DataCenterInfo datacenter) {
            this.result.dataCenterInfo = datacenter;
            return this;
        }

        public InstanceInfo.Builder setLeaseInfo(LeaseInfo info) {
            this.result.leaseInfo = info;
            return this;
        }

        public InstanceInfo.Builder add(String key, String val) {
            this.result.metadata.put(key, val);
            return this;
        }

        public InstanceInfo.Builder setMetadata(Map<String, String> mt) {
            this.result.metadata = mt;
            return this;
        }

        public InstanceInfo getRawInstance() {
            return this.result;
        }

        public InstanceInfo build() {
            if (!this.isInitialized()) {
                throw new IllegalStateException("name is required!");
            } else {
                return this.result;
            }
        }

        public boolean isInitialized() {
            return this.result.appName != null;
        }

        public InstanceInfo.Builder setASGName(String asgName) {
            this.result.asgName = (String)this.intern.apply(asgName);
            return this;
        }

        private InstanceInfo.Builder refreshStatusPageUrl() {
            this.setStatusPageUrl(this.result.statusPageRelativeUrl, this.result.statusPageExplicitUrl);
            return this;
        }

        private InstanceInfo.Builder refreshHealthCheckUrl() {
            this.setHealthCheckUrls(this.result.healthCheckRelativeUrl, this.result.healthCheckExplicitUrl, this.result.healthCheckSecureExplicitUrl);
            return this;
        }

        private InstanceInfo.Builder refreshSecureVIPAddress() {
            this.setSecureVIPAddress(this.result.secureVipAddressUnresolved);
            return this;
        }

        private InstanceInfo.Builder refreshVIPAddress() {
            this.setVIPAddress(this.result.vipAddressUnresolved);
            return this;
        }

        public InstanceInfo.Builder setIsCoordinatingDiscoveryServer(boolean isCoordinatingDiscoveryServer) {
            this.result.isCoordinatingDiscoveryServer = isCoordinatingDiscoveryServer;
            return this;
        }

        public InstanceInfo.Builder setLastUpdatedTimestamp(long lastUpdatedTimestamp) {
            this.result.lastUpdatedTimestamp = lastUpdatedTimestamp;
            return this;
        }

        public InstanceInfo.Builder setLastDirtyTimestamp(long lastDirtyTimestamp) {
            this.result.lastDirtyTimestamp = lastDirtyTimestamp;
            return this;
        }

        public InstanceInfo.Builder setActionType(InstanceInfo.ActionType actionType) {
            this.result.actionType = actionType;
            return this;
        }

        public InstanceInfo.Builder setNamespace(String namespace) {
            this.namespace = namespace.endsWith(".") ? namespace : namespace + ".";
            return this;
        }

        private static final class LazyHolder {
            private static final VipAddressResolver DEFAULT_VIP_ADDRESS_RESOLVER = new Archaius1VipAddressResolver();

            private LazyHolder() {
            }
        }
    }

    public static enum PortType {
        SECURE,
        UNSECURE;

        private PortType() {
        }
    }

    public static enum InstanceStatus {
        UP,
        DOWN,
        STARTING,
        OUT_OF_SERVICE,
        UNKNOWN;

        private InstanceStatus() {
        }

        public static InstanceInfo.InstanceStatus toEnum(String s) {
            if (s != null) {
                try {
                    return valueOf(s.toUpperCase());
                } catch (IllegalArgumentException var2) {
                    InstanceInfo.logger.debug("illegal argument supplied to InstanceStatus.valueOf: {}, defaulting to {}", s, UNKNOWN);
                }
            }

            return UNKNOWN;
        }
    }

    public static class PortWrapper {
        private final boolean enabled;
        private final int port;

        @JsonCreator
        public PortWrapper(@JsonProperty("@enabled") boolean enabled, @JsonProperty("$") int port) {
            this.enabled = enabled;
            this.port = port;
        }

        public boolean isEnabled() {
            return this.enabled;
        }

        public int getPort() {
            return this.port;
        }
    }
}

InstanceInfo封装了将被发送到Eureka Server进行注册的服务实例元数据

它在Eureka Server列表中代表一个服务实例,其他服务可以通过instanceInfo了解到该服务的实例相关信息,包括地址等,从而发起请求

查看EurekaInstanceConfig.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.appinfo;

import com.google.inject.ImplementedBy;
import java.util.Map;

@ImplementedBy(CloudInstanceConfig.class)
public interface EurekaInstanceConfig {
    String getInstanceId();

    String getAppname();

    String getAppGroupName();

    boolean isInstanceEnabledOnit();

    int getNonSecurePort();

    int getSecurePort();

    boolean isNonSecurePortEnabled();

    boolean getSecurePortEnabled();

    int getLeaseRenewalIntervalInSeconds();

    int getLeaseExpirationDurationInSeconds();

    String getVirtualHostName();

    String getSecureVirtualHostName();

    String getASGName();

    String getHostName(boolean var1);

    Map<String, String> getMetadataMap();

    DataCenterInfo getDataCenterInfo();

    String getIpAddress();

    String getStatusPageUrlPath();

    String getStatusPageUrl();

    String getHomePageUrlPath();

    String getHomePageUrl();

    String getHealthCheckUrlPath();

    String getHealthCheckUrl();

    String getSecureHealthCheckUrl();

    String[] getDefaultAddressResolutionOrder();

    String getNamespace();
}

这是个接口

CloudEurekaInstanceConfig继承了该类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.cloud.netflix.eureka;

import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;

public interface CloudEurekaInstanceConfig extends EurekaInstanceConfig {
    void setNonSecurePort(int port);

    void setSecurePort(int securePort);

    InstanceStatus getInitialStatus();
}

EurekaInstanceConfigBean实现了CloudEurekaInstanceConfig接口

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.cloud.netflix.eureka;

import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.MyDataCenterInfo;
import com.netflix.appinfo.DataCenterInfo.Name;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.commons.util.InetUtils;
import org.springframework.cloud.commons.util.InetUtils.HostInfo;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.util.StringUtils;

@ConfigurationProperties("eureka.instance")
public class EurekaInstanceConfigBean implements CloudEurekaInstanceConfig, EnvironmentAware {
    private static final String UNKNOWN = "unknown";
    private HostInfo hostInfo;
    private InetUtils inetUtils;
    private String actuatorPrefix = "/actuator";
    private String appname = "unknown";
    private String appGroupName;
    private boolean instanceEnabledOnit;
    private int nonSecurePort = 80;
    private int securePort = 443;
    private boolean nonSecurePortEnabled = true;
    private boolean securePortEnabled;
    private int leaseRenewalIntervalInSeconds = 30;
    private int leaseExpirationDurationInSeconds = 90;
    private String virtualHostName = "unknown";
    private String instanceId;
    private String secureVirtualHostName = "unknown";
    private String aSGName;
    private Map<String, String> metadataMap = new HashMap();
    private DataCenterInfo dataCenterInfo;
    private String ipAddress;
    private String statusPageUrlPath;
    private String statusPageUrl;
    private String homePageUrlPath;
    private String homePageUrl;
    private String healthCheckUrlPath;
    private String healthCheckUrl;
    private String secureHealthCheckUrl;
    private String namespace;
    private String hostname;
    private boolean preferIpAddress;
    private InstanceStatus initialStatus;
    private String[] defaultAddressResolutionOrder;
    private Environment environment;

    public String getHostname() {
        return this.getHostName(false);
    }

    private EurekaInstanceConfigBean() {
        this.dataCenterInfo = new MyDataCenterInfo(Name.MyOwn);
        this.statusPageUrlPath = this.actuatorPrefix + "/info";
        this.homePageUrlPath = "/";
        this.healthCheckUrlPath = this.actuatorPrefix + "/health";
        this.namespace = "eureka";
        this.preferIpAddress = false;
        this.initialStatus = InstanceStatus.UP;
        this.defaultAddressResolutionOrder = new String[0];
    }

    public EurekaInstanceConfigBean(InetUtils inetUtils) {
        this.dataCenterInfo = new MyDataCenterInfo(Name.MyOwn);
        this.statusPageUrlPath = this.actuatorPrefix + "/info";
        this.homePageUrlPath = "/";
        this.healthCheckUrlPath = this.actuatorPrefix + "/health";
        this.namespace = "eureka";
        this.preferIpAddress = false;
        this.initialStatus = InstanceStatus.UP;
        this.defaultAddressResolutionOrder = new String[0];
        this.inetUtils = inetUtils;
        this.hostInfo = this.inetUtils.findFirstNonLoopbackHostInfo();
        this.ipAddress = this.hostInfo.getIpAddress();
        this.hostname = this.hostInfo.getHostname();
    }

    public String getInstanceId() {
        return this.instanceId == null && this.metadataMap != null ? (String)this.metadataMap.get("instanceId") : this.instanceId;
    }

    public boolean getSecurePortEnabled() {
        return this.securePortEnabled;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
        this.hostInfo.override = true;
    }

    public void setIpAddress(String ipAddress) {
        this.ipAddress = ipAddress;
        this.hostInfo.override = true;
    }

    public String getHostName(boolean refresh) {
        if (refresh && !this.hostInfo.override) {
            this.ipAddress = this.hostInfo.getIpAddress();
            this.hostname = this.hostInfo.getHostname();
        }

        return this.preferIpAddress ? this.ipAddress : this.hostname;
    }

    public void setEnvironment(Environment environment) {
        this.environment = environment;
        String springAppName = this.environment.getProperty("spring.application.name", "");
        if (StringUtils.hasText(springAppName)) {
            this.setAppname(springAppName);
            this.setVirtualHostName(springAppName);
            this.setSecureVirtualHostName(springAppName);
        }

    }

    private HostInfo getHostInfo() {
        return this.hostInfo;
    }

    private void setHostInfo(HostInfo hostInfo) {
        this.hostInfo = hostInfo;
    }

    private InetUtils getInetUtils() {
        return this.inetUtils;
    }

    private void setInetUtils(InetUtils inetUtils) {
        this.inetUtils = inetUtils;
    }

    public String getAppname() {
        return this.appname;
    }

    public void setAppname(String appname) {
        this.appname = appname;
    }

    public String getAppGroupName() {
        return this.appGroupName;
    }

    public void setAppGroupName(String appGroupName) {
        this.appGroupName = appGroupName;
    }

    public boolean isInstanceEnabledOnit() {
        return this.instanceEnabledOnit;
    }

    public void setInstanceEnabledOnit(boolean instanceEnabledOnit) {
        this.instanceEnabledOnit = instanceEnabledOnit;
    }

    public int getNonSecurePort() {
        return this.nonSecurePort;
    }

    public void setNonSecurePort(int nonSecurePort) {
        this.nonSecurePort = nonSecurePort;
    }

    public int getSecurePort() {
        return this.securePort;
    }

    public void setSecurePort(int securePort) {
        this.securePort = securePort;
    }

    public boolean isNonSecurePortEnabled() {
        return this.nonSecurePortEnabled;
    }

    public void setNonSecurePortEnabled(boolean nonSecurePortEnabled) {
        this.nonSecurePortEnabled = nonSecurePortEnabled;
    }

    public boolean isSecurePortEnabled() {
        return this.securePortEnabled;
    }

    public void setSecurePortEnabled(boolean securePortEnabled) {
        this.securePortEnabled = securePortEnabled;
    }

    public int getLeaseRenewalIntervalInSeconds() {
        return this.leaseRenewalIntervalInSeconds;
    }

    public void setLeaseRenewalIntervalInSeconds(int leaseRenewalIntervalInSeconds) {
        this.leaseRenewalIntervalInSeconds = leaseRenewalIntervalInSeconds;
    }

    public int getLeaseExpirationDurationInSeconds() {
        return this.leaseExpirationDurationInSeconds;
    }

    public void setLeaseExpirationDurationInSeconds(int leaseExpirationDurationInSeconds) {
        this.leaseExpirationDurationInSeconds = leaseExpirationDurationInSeconds;
    }

    public String getVirtualHostName() {
        return this.virtualHostName;
    }

    public void setVirtualHostName(String virtualHostName) {
        this.virtualHostName = virtualHostName;
    }

    public void setInstanceId(String instanceId) {
        this.instanceId = instanceId;
    }

    public String getSecureVirtualHostName() {
        return this.secureVirtualHostName;
    }

    public void setSecureVirtualHostName(String secureVirtualHostName) {
        this.secureVirtualHostName = secureVirtualHostName;
    }

    public String getASGName() {
        return this.aSGName;
    }

    public void setASGName(String aSGName) {
        this.aSGName = aSGName;
    }

    public Map<String, String> getMetadataMap() {
        return this.metadataMap;
    }

    public void setMetadataMap(Map<String, String> metadataMap) {
        this.metadataMap = metadataMap;
    }

    public DataCenterInfo getDataCenterInfo() {
        return this.dataCenterInfo;
    }

    public void setDataCenterInfo(DataCenterInfo dataCenterInfo) {
        this.dataCenterInfo = dataCenterInfo;
    }

    public String getIpAddress() {
        return this.ipAddress;
    }

    public String getStatusPageUrlPath() {
        return this.statusPageUrlPath;
    }

    public void setStatusPageUrlPath(String statusPageUrlPath) {
        this.statusPageUrlPath = statusPageUrlPath;
    }

    public String getStatusPageUrl() {
        return this.statusPageUrl;
    }

    public void setStatusPageUrl(String statusPageUrl) {
        this.statusPageUrl = statusPageUrl;
    }

    public String getHomePageUrlPath() {
        return this.homePageUrlPath;
    }

    public void setHomePageUrlPath(String homePageUrlPath) {
        this.homePageUrlPath = homePageUrlPath;
    }

    public String getHomePageUrl() {
        return this.homePageUrl;
    }

    public void setHomePageUrl(String homePageUrl) {
        this.homePageUrl = homePageUrl;
    }

    public String getHealthCheckUrlPath() {
        return this.healthCheckUrlPath;
    }

    public void setHealthCheckUrlPath(String healthCheckUrlPath) {
        this.healthCheckUrlPath = healthCheckUrlPath;
    }

    public String getHealthCheckUrl() {
        return this.healthCheckUrl;
    }

    public void setHealthCheckUrl(String healthCheckUrl) {
        this.healthCheckUrl = healthCheckUrl;
    }

    public String getSecureHealthCheckUrl() {
        return this.secureHealthCheckUrl;
    }

    public void setSecureHealthCheckUrl(String secureHealthCheckUrl) {
        this.secureHealthCheckUrl = secureHealthCheckUrl;
    }

    public String getNamespace() {
        return this.namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    public boolean isPreferIpAddress() {
        return this.preferIpAddress;
    }

    public void setPreferIpAddress(boolean preferIpAddress) {
        this.preferIpAddress = preferIpAddress;
    }

    public InstanceStatus getInitialStatus() {
        return this.initialStatus;
    }

    public void setInitialStatus(InstanceStatus initialStatus) {
        this.initialStatus = initialStatus;
    }

    public String[] getDefaultAddressResolutionOrder() {
        return this.defaultAddressResolutionOrder;
    }

    public void setDefaultAddressResolutionOrder(String[] defaultAddressResolutionOrder) {
        this.defaultAddressResolutionOrder = defaultAddressResolutionOrder;
    }

    public Environment getEnvironment() {
        return this.environment;
    }

    public boolean equals(Object o) {
        if (this == o) {
            return true;
        } else if (o != null && this.getClass() == o.getClass()) {
            EurekaInstanceConfigBean that = (EurekaInstanceConfigBean)o;
            return Objects.equals(this.hostInfo, that.hostInfo) && Objects.equals(this.inetUtils, that.inetUtils) && Objects.equals(this.appname, that.appname) && Objects.equals(this.appGroupName, that.appGroupName) && this.instanceEnabledOnit == that.instanceEnabledOnit && this.nonSecurePort == that.nonSecurePort && this.securePort == that.securePort && this.nonSecurePortEnabled == that.nonSecurePortEnabled && this.securePortEnabled == that.securePortEnabled && this.leaseRenewalIntervalInSeconds == that.leaseRenewalIntervalInSeconds && this.leaseExpirationDurationInSeconds == that.leaseExpirationDurationInSeconds && Objects.equals(this.virtualHostName, that.virtualHostName) && Objects.equals(this.instanceId, that.instanceId) && Objects.equals(this.secureVirtualHostName, that.secureVirtualHostName) && Objects.equals(this.aSGName, that.aSGName) && Objects.equals(this.metadataMap, that.metadataMap) && Objects.equals(this.dataCenterInfo, that.dataCenterInfo) && Objects.equals(this.ipAddress, that.ipAddress) && Objects.equals(this.statusPageUrlPath, that.statusPageUrlPath) && Objects.equals(this.statusPageUrl, that.statusPageUrl) && Objects.equals(this.homePageUrlPath, that.homePageUrlPath) && Objects.equals(this.homePageUrl, that.homePageUrl) && Objects.equals(this.healthCheckUrlPath, that.healthCheckUrlPath) && Objects.equals(this.healthCheckUrl, that.healthCheckUrl) && Objects.equals(this.secureHealthCheckUrl, that.secureHealthCheckUrl) && Objects.equals(this.namespace, that.namespace) && Objects.equals(this.hostname, that.hostname) && this.preferIpAddress == that.preferIpAddress && Objects.equals(this.initialStatus, that.initialStatus) && Arrays.equals(this.defaultAddressResolutionOrder, that.defaultAddressResolutionOrder) && Objects.equals(this.environment, that.environment);
        } else {
            return false;
        }
    }

    public int hashCode() {
        return Objects.hash(new Object[]{this.hostInfo, this.inetUtils, this.appname, this.appGroupName, this.instanceEnabledOnit, this.nonSecurePort, this.securePort, this.nonSecurePortEnabled, this.securePortEnabled, this.leaseRenewalIntervalInSeconds, this.leaseExpirationDurationInSeconds, this.virtualHostName, this.instanceId, this.secureVirtualHostName, this.aSGName, this.metadataMap, this.dataCenterInfo, this.ipAddress, this.statusPageUrlPath, this.statusPageUrl, this.homePageUrlPath, this.homePageUrl, this.healthCheckUrlPath, this.healthCheckUrl, this.secureHealthCheckUrl, this.namespace, this.hostname, this.preferIpAddress, this.initialStatus, this.defaultAddressResolutionOrder, this.environment});
    }

    public String toString() {
        return "EurekaInstanceConfigBean{" + "hostInfo=" + this.hostInfo + ", " + "inetUtils=" + this.inetUtils + ", " + "appname='" + this.appname + "', " + "appGroupName='" + this.appGroupName + "', " + "instanceEnabledOnit=" + this.instanceEnabledOnit + ", " + "nonSecurePort=" + this.nonSecurePort + ", " + "securePort=" + this.securePort + ", " + "nonSecurePortEnabled=" + this.nonSecurePortEnabled + ", " + "securePortEnabled=" + this.securePortEnabled + ", " + "leaseRenewalIntervalInSeconds=" + this.leaseRenewalIntervalInSeconds + ", " + "leaseExpirationDurationInSeconds=" + this.leaseExpirationDurationInSeconds + ", " + "virtualHostName='" + this.virtualHostName + "', " + "instanceId='" + this.instanceId + "', " + "secureVirtualHostName='" + this.secureVirtualHostName + "', " + "aSGName='" + this.aSGName + "', " + "metadataMap=" + this.metadataMap + ", " + "dataCenterInfo=" + this.dataCenterInfo + ", " + "ipAddress='" + this.ipAddress + "', " + "statusPageUrlPath='" + this.statusPageUrlPath + "', " + "statusPageUrl='" + this.statusPageUrl + "', " + "homePageUrlPath='" + this.homePageUrlPath + "', " + "homePageUrl='" + this.homePageUrl + "', " + "healthCheckUrlPath='" + this.healthCheckUrlPath + "', " + "healthCheckUrl='" + this.healthCheckUrl + "', " + "secureHealthCheckUrl='" + this.secureHealthCheckUrl + "', " + "namespace='" + this.namespace + "', " + "hostname='" + this.hostname + "', " + "preferIpAddress=" + this.preferIpAddress + ", " + "initialStatus=" + this.initialStatus + ", " + "defaultAddressResolutionOrder=" + Arrays.toString(this.defaultAddressResolutionOrder) + ", " + "environment=" + this.environment + ", " + "}";
    }
}

找到其实现类CloudInstanceConfig.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.appinfo;

import com.google.inject.ProvidedBy;
import com.netflix.appinfo.AmazonInfo.MetaDataKey;
import com.netflix.appinfo.RefreshableAmazonInfoProvider.FallbackAddressProvider;
import com.netflix.appinfo.providers.CloudInstanceConfigProvider;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@ProvidedBy(CloudInstanceConfigProvider.class)
public class CloudInstanceConfig extends PropertiesInstanceConfig implements RefreshableInstanceConfig {
    private static final Logger logger = LoggerFactory.getLogger(CloudInstanceConfig.class);
    private static final String[] DEFAULT_AWS_ADDRESS_RESOLUTION_ORDER;
    private final RefreshableAmazonInfoProvider amazonInfoHolder;

    public CloudInstanceConfig() {
        this("eureka");
    }

    public CloudInstanceConfig(String namespace) {
        this(namespace, new Archaius1AmazonInfoConfig(namespace), (AmazonInfo)null, true);
    }

    CloudInstanceConfig(AmazonInfo info) {
        this("eureka", new Archaius1AmazonInfoConfig("eureka"), info, false);
    }

    CloudInstanceConfig(String namespace, RefreshableAmazonInfoProvider refreshableAmazonInfoProvider) {
        super(namespace);
        this.amazonInfoHolder = refreshableAmazonInfoProvider;
    }

    CloudInstanceConfig(String namespace, AmazonInfoConfig amazonInfoConfig, AmazonInfo initialInfo, boolean eagerInit) {
        super(namespace);
        if (eagerInit) {
            FallbackAddressProvider fallbackAddressProvider = new FallbackAddressProvider() {
                public String getFallbackIp() {
                    return CloudInstanceConfig.super.getIpAddress();
                }

                public String getFallbackHostname() {
                    return CloudInstanceConfig.super.getHostName(false);
                }
            };
            this.amazonInfoHolder = new RefreshableAmazonInfoProvider(amazonInfoConfig, fallbackAddressProvider);
        } else {
            this.amazonInfoHolder = new RefreshableAmazonInfoProvider(initialInfo, amazonInfoConfig);
        }

    }

    /** @deprecated */
    @Deprecated
    public String resolveDefaultAddress() {
        return this.resolveDefaultAddress(true);
    }

    public String resolveDefaultAddress(boolean refresh) {
        String result = this.getHostName(refresh);
        String[] var3 = this.getDefaultAddressResolutionOrder();
        int var4 = var3.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String name = var3[var5];

            try {
                MetaDataKey key = MetaDataKey.valueOf(name);
                String address = this.amazonInfoHolder.get().get(key);
                if (address != null && !address.isEmpty()) {
                    result = address;
                    break;
                }
            } catch (Exception var9) {
                logger.error("failed to resolve default address for key {}, skipping", name, var9);
            }
        }

        return result;
    }

    public String getHostName(boolean refresh) {
        if (refresh) {
            this.amazonInfoHolder.refresh();
        }

        return this.amazonInfoHolder.get().get(MetaDataKey.publicHostname);
    }

    public String getIpAddress() {
        String ipAddr = this.amazonInfoHolder.get().get(MetaDataKey.localIpv4);
        return ipAddr == null ? super.getIpAddress() : ipAddr;
    }

    public DataCenterInfo getDataCenterInfo() {
        return this.amazonInfoHolder.get();
    }

    public String[] getDefaultAddressResolutionOrder() {
        String[] order = super.getDefaultAddressResolutionOrder();
        return order.length == 0 ? DEFAULT_AWS_ADDRESS_RESOLUTION_ORDER : order;
    }

    /** @deprecated */
    @Deprecated
    public synchronized void refreshAmazonInfo() {
        this.amazonInfoHolder.refresh();
    }

    /** @deprecated */
    @Deprecated
    static boolean shouldUpdate(AmazonInfo newInfo, AmazonInfo oldInfo) {
        return RefreshableAmazonInfoProvider.shouldUpdate(newInfo, oldInfo);
    }

    static {
        DEFAULT_AWS_ADDRESS_RESOLUTION_ORDER = new String[]{MetaDataKey.publicHostname.name(), MetaDataKey.localIpv4.name()};
    }
}

此类封装了EurekaClient自身服务实例的配置信息,主要用于构建InstanceInfo

看到此类有一段代码

  • @ConfigurationProperties("eureka.instance"), 在配置文件中用eureka.instance.属性配置
  • EurekaInstanceConfigBean提供了默认值

在ApplicationInfoManager中有一个方法

public void initComponent(EurekaInstanceConfig config) {
    try {
        this.config = config;
        this.instanceInfo = (new EurekaConfigBasedInstanceInfoProvider(config)).get();
    } catch (Throwable var3) {
        throw new RuntimeException("Failed to initialize ApplicationInfoManager", var3);
    }
}

查看EurekaConfigBasedInstanceInfoProvider.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.appinfo.providers;

import com.google.inject.Inject;
import com.netflix.appinfo.DataCenterInfo;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.appinfo.RefreshableInstanceConfig;
import com.netflix.appinfo.UniqueIdentifier;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
import com.netflix.appinfo.InstanceInfo.PortType;
import com.netflix.appinfo.LeaseInfo.Builder;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
public class EurekaConfigBasedInstanceInfoProvider implements Provider<InstanceInfo> {
    private static final Logger LOG = LoggerFactory.getLogger(EurekaConfigBasedInstanceInfoProvider.class);
    private final EurekaInstanceConfig config;
    private InstanceInfo instanceInfo;
    @Inject(
        optional = true
    )
    private VipAddressResolver vipAddressResolver = null;

    @Inject
    public EurekaConfigBasedInstanceInfoProvider(EurekaInstanceConfig config) {
        this.config = config;
    }

    public synchronized InstanceInfo get() {
        if (this.instanceInfo == null) {
            Builder leaseInfoBuilder = Builder.newBuilder().setRenewalIntervalInSecs(this.config.getLeaseRenewalIntervalInSeconds()).setDurationInSecs(this.config.getLeaseExpirationDurationInSeconds());
            if (this.vipAddressResolver == null) {
                this.vipAddressResolver = new Archaius1VipAddressResolver();
            }

            com.netflix.appinfo.InstanceInfo.Builder builder = com.netflix.appinfo.InstanceInfo.Builder.newBuilder(this.vipAddressResolver);
            String instanceId = this.config.getInstanceId();
            if (instanceId == null || instanceId.isEmpty()) {
                DataCenterInfo dataCenterInfo = this.config.getDataCenterInfo();
                if (dataCenterInfo instanceof UniqueIdentifier) {
                    instanceId = ((UniqueIdentifier)dataCenterInfo).getId();
                } else {
                    instanceId = this.config.getHostName(false);
                }
            }

            String defaultAddress;
            if (this.config instanceof RefreshableInstanceConfig) {
                defaultAddress = ((RefreshableInstanceConfig)this.config).resolveDefaultAddress(false);
            } else {
                defaultAddress = this.config.getHostName(false);
            }

            if (defaultAddress == null || defaultAddress.isEmpty()) {
                defaultAddress = this.config.getIpAddress();
            }

            builder.setNamespace(this.config.getNamespace()).setInstanceId(instanceId).setAppName(this.config.getAppname()).setAppGroupName(this.config.getAppGroupName()).setDataCenterInfo(this.config.getDataCenterInfo()).setIPAddr(this.config.getIpAddress()).setHostName(defaultAddress).setPort(this.config.getNonSecurePort()).enablePort(PortType.UNSECURE, this.config.isNonSecurePortEnabled()).setSecurePort(this.config.getSecurePort()).enablePort(PortType.SECURE, this.config.getSecurePortEnabled()).setVIPAddress(this.config.getVirtualHostName()).setSecureVIPAddress(this.config.getSecureVirtualHostName()).setHomePageUrl(this.config.getHomePageUrlPath(), this.config.getHomePageUrl()).setStatusPageUrl(this.config.getStatusPageUrlPath(), this.config.getStatusPageUrl()).setASGName(this.config.getASGName()).setHealthCheckUrls(this.config.getHealthCheckUrlPath(), this.config.getHealthCheckUrl(), this.config.getSecureHealthCheckUrl());
            if (!this.config.isInstanceEnabledOnit()) {
                InstanceStatus initialStatus = InstanceStatus.STARTING;
                LOG.info("Setting initial instance status as: {}", initialStatus);
                builder.setStatus(initialStatus);
            } else {
                LOG.info("Setting initial instance status as: {}. This may be too early for the instance to advertise itself as available. You would instead want to control this via a healthcheck handler.", InstanceStatus.UP);
            }

            Iterator var10 = this.config.getMetadataMap().entrySet().iterator();

            while(var10.hasNext()) {
                Entry<String, String> mapEntry = (Entry)var10.next();
                String key = (String)mapEntry.getKey();
                String value = (String)mapEntry.getValue();
                if (value != null && !value.isEmpty()) {
                    builder.add(key, value);
                }
            }

            this.instanceInfo = builder.build();
            this.instanceInfo.setLeaseInfo(leaseInfoBuilder.build());
        }

        return this.instanceInfo;
    }
}

发现正是通过EurekaInstanceConfig构造instanceInfo

顶级接口DiscoveryClient

eurekaClient的父类LookupService.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.netflix.discovery.shared;

import com.netflix.appinfo.InstanceInfo;
import java.util.List;

public interface LookupService<T> {
    Application getApplication(String var1);

    Applications getApplications();

    List<InstanceInfo> getInstancesById(String var1);

    InstanceInfo getNextServerFromEureka(String var1, boolean var2);
}

LookupService作用:发现活跃的服务实例

  • 根据服务实例注册的appName来获取封装有相同appName的服务实例信息容器,Application getApplication(String appName)
  • 获取所有的服务实例信息,Applications getApplications()
  • 根据实例id,获取服务实例信息,List getInstancesById(String id)

上面提到一个Application,它持有服务实例信息列表,它是同一个服务的集群信息

Applications是注册表中,所有服务实例信息的集合

instanceInfo代表一个服务实例的信息

为了保证原子性,比如对某个instanceInfo的操作,使用了大量同步的代码

比如下面代码: 

public void addInstance(InstanceInfo i) { 
instancesMap.put(i.getId(), i);
synchronized (instances) {
instances.remove(i);
instances.add(i);
isDirty = true;
}
}

免责声明:文章转载自《Eureka Client 加载过程以及源码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇HBase 表操作网络抓包神器 Tcpdump 使用指南下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

(转)在CentOS中修改中文字符集

本文介绍在linux的shell环境下优化linux中文显示的方法。在CentOS7以前的版本下,默认的字符集的路径一般保存在/etc/sysconfig/i18n文件中。但是在CentOS7版本中,字符集配置文件位于/etc/locale.conf。通过source命令即可使修改生效:[ruby]viewplaincopy#source/etc/local...

【使用 DOM】为DOM元素设置样式

DOCTYPE html˃设置DOM元素的样式p{border:中双绿色;背景颜色:浅灰色;}#block1{color:白色;}table{border:thinsolided;border collapse:collapse;margin:5px;float:left;}td{padding:2px;}#block2{color:yellow;font-...

Spark 数据读取与保存(输入、输出)

SaveAsTextFile(字符串)scala&gt:importsscala.util.parsing.json.json(2)将json文件上载到HDFS[lxl@hadoop102spark]$hadoopfs投入。/示例/src/main/resources/people。json/(3)读取文件scala&gt;...

(二)Jenkins配置主从节点实例

4.从节点配置和相关配置中从节点机创建jenkins用户,并从一些环境配置中创建jenkings用户的ssh密钥,用于指定上述配置界面的ssh启动模式;在配置启动模式和项目源代码管理中从远程仓库获取源代码;创建Jenkins用户并使用root登录到远程子节点计算机。#adduserjenkins#passwdjenkins生成Jenkins用户的ssh密钥。...

CUPS

杯子:一个。工具1.hal设备管理器2.系统配置打印机3.Web管理器/etc/cups/ccups。conf/etc/cups/printer conf II。打印机本地安装和客户端安装1.在本地安装Linux打印机时,应选择postscript和pcl打印机。如果没有,则应将打印机设置为原始打印模式/etc/cups/printers。有限公司...

mac下vscode插件位置

1、 位置:Mac:User/(您的用户名)/vscode/extensions II下vscode插件的存储位置。搜索步骤:以我的mac为例,打开查找器,单击远程CD,单击转到上面的文件夹,单击macintosh HD,单击用户(或用户),单击mymac,单击。vscode(.vscode是一个隐藏文件。如果默认情况下不显示,请按住ctrl+shift+....