zoukankan      html  css  js  c++  java
  • Eureka Client 加载过程以及源码

    Eureka架构图

    角色分析

    服务提供者

    是一个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

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

    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实现类

    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;
    }
    }
    论读书
    睁开眼,书在面前
    闭上眼,书在心里
  • 相关阅读:
    新年后的第一个学习总结
    2021/02/07周学习总结
    内网穿透
    有效的括号
    实现一个简单的模板字符串替换
    二叉树的最大深度
    前端性能和错误监控
    前端缓存
    display: none; opacity: 0; visibility: hidden;
    发布订阅模式与观察者模式
  • 原文地址:https://www.cnblogs.com/YC-L/p/14474683.html
Copyright © 2011-2022 走看看