eureka客户端源码解析
来源:互联网 发布:铁路造价软件 编辑:程序博客网 时间:2024/05/22 16:51
原文:https://blog.tookbra.com/2017/08/25/Spring-Cloud-Eureka-Client-Source/
源码目录结构
.├── pom.xml└── src ├── main │ ├── java │ │ └── org │ │ └── springframework │ │ └── cloud │ │ └── netflix │ │ ├── eureka │ │ │ ├── CloudEurekaClient.java │ │ │ ├── CloudEurekaInstanceConfig.java │ │ │ ├── CloudEurekaTransportConfig.java │ │ │ ├── EnableEurekaClient.java │ │ │ ├── EurekaClientAutoConfiguration.java │ │ │ ├── EurekaClientConfigBean.java │ │ │ ├── EurekaConstants.java │ │ │ ├── EurekaDiscoveryClient.java │ │ │ ├── EurekaDiscoveryClientConfiguration.java │ │ │ ├── EurekaHealthCheckHandler.java │ │ │ ├── EurekaHealthIndicator.java │ │ │ ├── EurekaInstanceConfigBean.java │ │ │ ├── InstanceInfoFactory.java │ │ │ ├── MutableDiscoveryClientOptionalArgs.java │ │ │ ├── config │ │ │ │ ├── DiscoveryClientOptionalArgsConfiguration.java │ │ │ │ ├── EurekaClientConfigServerAutoConfiguration.java │ │ │ │ ├── EurekaDiscoveryClientConfigServiceAutoConfiguration.java │ │ │ │ └── EurekaDiscoveryClientConfigServiceBootstrapConfiguration.java │ │ │ ├── http │ │ │ │ ├── EurekaApplications.java │ │ │ │ ├── RestTemplateDiscoveryClientOptionalArgs.java │ │ │ │ ├── RestTemplateEurekaHttpClient.java │ │ │ │ ├── RestTemplateTransportClientFactories.java │ │ │ │ └── RestTemplateTransportClientFactory.java │ │ │ └── serviceregistry │ │ │ ├── EurekaAutoServiceRegistration.java │ │ │ ├── EurekaRegistration.java │ │ │ └── EurekaServiceRegistry.java │ │ └── ribbon │ │ └── eureka │ │ ├── DomainExtractingServerList.java │ │ ├── EurekaRibbonClientConfiguration.java │ │ ├── EurekaServerIntrospector.java │ │ ├── RibbonEurekaAutoConfiguration.java │ │ └── ZoneUtils.java │ └── resources │ └── META-INF │ └── spring.factories └── test ├── java │ └── org │ └── springframework │ └── cloud │ └── netflix │ ├── eureka │ │ ├── ConditionalOnRefreshScopeTests.java │ │ ├── EurekaClientAutoConfigurationTests.java │ │ ├── EurekaClientConfigBeanTests.java │ │ ├── EurekaHealthCheckHandlerTests.java │ │ ├── EurekaInstanceConfigBeanTests.java │ │ ├── InstanceInfoFactoryTests.java │ │ ├── config │ │ │ ├── ConfigRefreshTests.java │ │ │ ├── DiscoveryClientConfigServiceAutoConfigurationTests.java │ │ │ ├── EurekaClientConfigServerAutoConfigurationTests.java │ │ │ ├── JerseyOptionalArgsConfigurationTest.java │ │ │ └── RestTemplateOptionalArgsConfigurationTest.java │ │ ├── healthcheck │ │ │ └── EurekaHealthCheckTests.java │ │ ├── http │ │ │ ├── EurekaServerMockApplication.java │ │ │ ├── RestTemplateEurekaHttpClientTest.java │ │ │ ├── RestTemplateTransportClientFactoriesTest.java │ │ │ └── RestTemplateTransportClientFactoryTest.java │ │ ├── sample │ │ │ ├── ApplicationTests.java │ │ │ ├── EurekaSampleApplication.java │ │ │ └── RefreshEurekaSampleApplication.java │ │ └── serviceregistry │ │ └── EurekaServiceRegistryTests.java │ └── ribbon │ └── eureka │ ├── DomainExtractingServerListTests.java │ ├── EurekaDisabledRibbonClientIntegrationTests.java │ ├── EurekaRibbonClientConfigurationTests.java │ ├── EurekaRibbonClientPreprocessorIntegrationTests.java │ ├── EurekaRibbonClientPropertyOverrideIntegrationTests.java │ ├── RibbonClientPreprocessorIntegrationTests.java │ ├── RibbonEurekaAutoConfigurationTests.java │ └── ZoneUtilsTests.java └── resources └── application.yml
客户端启动分析
@SpringBootApplication@EnableDiscoveryClientpublic class ClientApplication { public static void main(String[] args) { SpringApplication.run(ClientApplication.class, args); }}
@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@Import({EnableDiscoveryClientImportSelector.class})public @interface EnableDiscoveryClient { boolean autoRegister() default true;}
@Order(Ordered.LOWEST_PRECEDENCE - 100)public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> { @Override public String[] selectImports(AnnotationMetadata metadata) { String[] imports = super.selectImports(metadata); AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(getAnnotationClass().getName(), true)); boolean autoRegister = attributes.getBoolean("autoRegister"); if (autoRegister) { List<String> importsList = new ArrayList<>(Arrays.asList(imports)); importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration"); imports = importsList.toArray(new String[0]); } return imports; } ...}
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.RibbonEurekaAutoConfigurationorg.springframework.cloud.bootstrap.BootstrapConfiguration=\org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceBootstrapConfigurationorg.springframework.cloud.client.discovery.EnableDiscoveryClient=\org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration
@Order(2147483547)public class EnableDiscoveryClientImportSelector extends SpringFactoryImportSelector<EnableDiscoveryClient> { public EnableDiscoveryClientImportSelector() { } //返回需要加载的EurekaDiscoveryClientConfiguration bean public String[] selectImports(AnnotationMetadata metadata) { //org.springframework.cloud.client.discovery.EnableDiscoveryClient=\org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration String[] imports = super.selectImports(metadata); AnnotationAttributes attributes = AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(this.getAnnotationClass().getName(), true)); boolean autoRegister = attributes.getBoolean("autoRegister"); if(autoRegister) { List<String> importsList = new ArrayList(Arrays.asList(imports)); importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration"); imports = (String[])importsList.toArray(new String[0]); } return imports; } protected boolean isEnabled() { return ((Boolean)(new RelaxedPropertyResolver(this.getEnvironment())).getProperty("spring.cloud.discovery.enabled", Boolean.class, Boolean.TRUE)).booleanValue(); } protected boolean hasDefaultFactory() { return true; }}
@Configuration@EnableConfigurationProperties@ConditionalOnClass(EurekaClientConfig.class)@ConditionalOnBean(EurekaDiscoveryClientConfiguration.Marker.class)@ConditionalOnProperty(value = "eureka.client.enabled", matchIfMissing = true)@AutoConfigureBefore({ NoopDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class, ServiceRegistryAutoConfiguration.class })@AutoConfigureAfter(name = "org.springframework.cloud.autoconfigure.RefreshAutoConfiguration")public class EurekaClientAutoConfiguration { ... @Bean public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) { return new EurekaDiscoveryClient(config, client); } @Configuration @ConditionalOnRefreshScope protected static class RefreshableEurekaClientConfiguration { @Autowired private ApplicationContext context; @Autowired(required = false) private DiscoveryClientOptionalArgs optionalArgs; @Bean(destroyMethod = "shutdown") @ConditionalOnMissingBean(value = EurekaClient.class, search = SearchStrategy.CURRENT) @org.springframework.cloud.context.config.annotation.RefreshScope @Lazy public EurekaClient eurekaClient(ApplicationInfoManager manager, EurekaClientConfig config, EurekaInstanceConfig instance) { manager.getInfo(); // force initialization return new CloudEurekaClient(manager, config, this.optionalArgs, this.context); } @Bean @ConditionalOnMissingBean(value = ApplicationInfoManager.class, search = SearchStrategy.CURRENT) @org.springframework.cloud.context.config.annotation.RefreshScope @Lazy public ApplicationInfoManager eurekaApplicationInfoManager( EurekaInstanceConfig config) { InstanceInfo instanceInfo = new InstanceInfoFactory().create(config); return new ApplicationInfoManager(config, instanceInfo); } } @Bean public DiscoveryClient discoveryClient(EurekaInstanceConfig config, EurekaClient client) { return new EurekaDiscoveryClient(config, client); } ...}
public class EurekaAutoServiceRegistration implements AutoServiceRegistration, SmartLifecycle, Ordered { ... @Override public void start() { // only set the port if the nonSecurePort is 0 and this.port != 0 if (this.port.get() != 0 && this.registration.getNonSecurePort() == 0) { this.registration.setNonSecurePort(this.port.get()); } // only initialize if nonSecurePort is greater than 0 and it isn't already running // because of containerPortInitializer below if (!this.running.get() && this.registration.getNonSecurePort() > 0) { // 设置 eureka 初始化状态 eureka.instance.initial-status this.serviceRegistry.register(this.registration); // 传递eureka注册事件 // DiscoveryClientHealthIndicator类监听 this.context.publishEvent( new InstanceRegisteredEvent<>(this, this.registration.getInstanceConfig())); // 设置在spring容器关闭的时候执行stop方法 this.running.set(true); } } ....}
public class EurekaServiceRegistry implements ServiceRegistry<EurekaRegistration> { public void register(EurekaRegistration reg) { maybeInitializeClient(reg); if (log.isInfoEnabled()) { log.info("Registering application " + reg.getInstanceConfig().getAppname() + " with eureka with status " + reg.getInstanceConfig().getInitialStatus()); } reg.getApplicationInfoManager() .setInstanceStatus(reg.getInstanceConfig().getInitialStatus()); if (reg.getHealthCheckHandler() != null) { reg.getEurekaClient().registerHealthCheck(reg.getHealthCheckHandler()); } }}
@Singletonpublic class DiscoveryClient implements EurekaClient { @Inject DiscoveryClient(ApplicationInfoManager applicationInfoManager, EurekaClientConfig config, AbstractDiscoveryClientOptionalArgs args, Provider<BackupRegistry> backupRegistryProvider) { if (args != null) { this.healthCheckHandlerProvider = args.healthCheckHandlerProvider; this.healthCheckCallbackProvider = args.healthCheckCallbackProvider; this.eventListeners.addAll(args.getEventListeners()); } else { this.healthCheckCallbackProvider = null; this.healthCheckHandlerProvider = null; } this.applicationInfoManager = applicationInfoManager; //获取 instance InstanceInfo myInfo = applicationInfoManager.getInfo(); //客户端配置 clientConfig = config; staticClientConfig = clientConfig; //传输配置,心跳时间等 transportConfig = config.getTransportConfig(); instanceInfo = myInfo; if (myInfo != null) { appPathIdentifier = instanceInfo.getAppName() + "/" + instanceInfo.getId(); } else { logger.warn("Setting instanceInfo to a passed in null value"); } this.backupRegistryProvider = backupRegistryProvider; this.urlRandomizer = new EndpointUtils.InstanceInfoBasedUrlRandomizer(instanceInfo); localRegionApps.set(new Applications()); fetchRegistryGeneration = new AtomicLong(0); remoteRegionsToFetch = new AtomicReference<String>(clientConfig.fetchRegistryForRemoteRegions()); remoteRegionsRef = new AtomicReference<>(remoteRegionsToFetch.get() == null ? null : remoteRegionsToFetch.get().split(",")); //是否需要信息检索 eureka.client.fetchRegistry=true // if (config.shouldFetchRegistry()) { this.registryStalenessMonitor = new ThresholdLevelsMetric(this, METRIC_REGISTRY_PREFIX + "lastUpdateSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L}); } else { this.registryStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC; } //是否注册到eureka eureka.client.registerWithEureka=true if (config.shouldRegisterWithEureka()) { this.heartbeatStalenessMonitor = new ThresholdLevelsMetric(this, METRIC_REGISTRATION_PREFIX + "lastHeartbeatSec_", new long[]{15L, 30L, 60L, 120L, 240L, 480L}); } else { this.heartbeatStalenessMonitor = ThresholdLevelsMetric.NO_OP_METRIC; } logger.info("Initializing Eureka in region {}", clientConfig.getRegion()); //如果不开启注册到eureka和从eureka检索服务 //把定时任务、心跳设置为null if (!config.shouldRegisterWithEureka() && !config.shouldFetchRegistry()) { logger.info("Client configured to neither register nor query for data."); scheduler = null; heartbeatExecutor = null; cacheRefreshExecutor = null; eurekaTransport = null; instanceRegionChecker = new InstanceRegionChecker(new PropertyBasedAzToRegionMapper(config), clientConfig.getRegion()); // This is a bit of hack to allow for existing code using DiscoveryManager.getInstance() // to work with DI'd DiscoveryClient DiscoveryManager.getInstance().setDiscoveryClient(this); DiscoveryManager.getInstance().setEurekaClientConfig(config); initTimestampMs = System.currentTimeMillis(); logger.info("Discovery Client initialized at timestamp {} with initial instances count: {}", initTimestampMs, this.getApplications().size()); return; // no need to setup up an network tasks and we are done } // 配置作业 try { scheduler = Executors.newScheduledThreadPool(3, new ThreadFactoryBuilder() .setNameFormat("DiscoveryClient-%d") .setDaemon(true) .build()); heartbeatExecutor = new ThreadPoolExecutor( 1, clientConfig.getHeartbeatExecutorThreadPoolSize(), 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactoryBuilder() .setNameFormat("DiscoveryClient-HeartbeatExecutor-%d") .setDaemon(true) .build() ); // use direct handoff cacheRefreshExecutor = new ThreadPoolExecutor( 1, clientConfig.getCacheRefreshExecutorThreadPoolSize(), 0, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadFactoryBuilder() .setNameFormat("DiscoveryClient-CacheRefreshExecutor-%d") .setDaemon(true) .build() ); // use direct handoff eurekaTransport = new EurekaTransport(); scheduleServerEndpointTask(eurekaTransport, args); AzToRegionMapper azToRegionMapper; // eureka.client.use-dns-for-fetching-service-urls if (clientConfig.shouldUseDnsForFetchingServiceUrls()) { azToRegionMapper = new DNSBasedAzToRegionMapper(clientConfig); } else { azToRegionMapper = new PropertyBasedAzToRegionMapper(clientConfig); } if (null != remoteRegionsToFetch.get()) { azToRegionMapper.setRegionsToFetch(remoteRegionsToFetch.get().split(",")); } instanceRegionChecker = new InstanceRegionChecker(azToRegionMapper, clientConfig.getRegion()); } catch (Throwable e) { throw new RuntimeException("Failed to initialize DiscoveryClient!", e); } //刷新服务注册地址 if (clientConfig.shouldFetchRegistry() && !fetchRegistry(false)) { fetchRegistryFromBackup(); } //初始化作业,心跳,状态、缓存 initScheduledTasks(); try { Monitors.registerObject(this); } catch (Throwable e) { logger.warn("Cannot register timers", e); } // This is a bit of hack to allow for existing code using DiscoveryManager.getInstance() // to work with DI'd DiscoveryClient DiscoveryManager.getInstance().setDiscoveryClient(this); DiscoveryManager.getInstance().setEurekaClientConfig(config); initTimestampMs = System.currentTimeMillis(); logger.info("Discovery Client initialized at timestamp {} with initial instances count: {}", initTimestampMs, this.getApplications().size()); } /** * Register with the eureka service by making the appropriate REST call. */ boolean register() throws Throwable { logger.info(PREFIX + appPathIdentifier + ": registering service..."); EurekaHttpResponse<Void> httpResponse; try { httpResponse = eurekaTransport.registrationClient.register(instanceInfo); } catch (Exception e) { logger.warn("{} - registration failed {}", PREFIX + appPathIdentifier, e.getMessage(), e); throw e; } if (logger.isInfoEnabled()) { logger.info("{} - registration status: {}", PREFIX + appPathIdentifier, httpResponse.getStatusCode()); } return httpResponse.getStatusCode() == 204; }}
public class ApplicationInfoManager { public synchronized void setInstanceStatus(InstanceStatus status) { InstanceStatus next = instanceStatusMapper.map(status); if (next == null) { return; } InstanceStatus prev = instanceInfo.setStatus(next); if (prev != null) { for (StatusChangeListener listener : listeners.values()) { try { //状态改变 listener.notify(new StatusChangeEvent(prev, next)); } catch (Exception e) { logger.warn("failed to notify listener: {}", listener.getId(), e); } } } }}
private void initScheduledTasks() { if (clientConfig.shouldFetchRegistry()) { // registry cache refresh timer int registryFetchIntervalSeconds = clientConfig.getRegistryFetchIntervalSeconds(); int expBackOffBound = clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); scheduler.schedule( new TimedSupervisorTask( "cacheRefresh", scheduler, cacheRefreshExecutor, registryFetchIntervalSeconds, TimeUnit.SECONDS, expBackOffBound, new CacheRefreshThread() ), registryFetchIntervalSeconds, TimeUnit.SECONDS); } if (clientConfig.shouldRegisterWithEureka()) { int renewalIntervalInSecs = instanceInfo.getLeaseInfo().getRenewalIntervalInSecs(); int expBackOffBound = clientConfig.getHeartbeatExecutorExponentialBackOffBound(); logger.info("Starting heartbeat executor: " + "renew interval is: " + renewalIntervalInSecs); // Heartbeat timer scheduler.schedule( new TimedSupervisorTask( "heartbeat", scheduler, heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new HeartbeatThread() ), renewalIntervalInSecs, TimeUnit.SECONDS); // InstanceInfo replicator instanceInfoReplicator = new InstanceInfoReplicator( this, instanceInfo, clientConfig.getInstanceInfoReplicationIntervalSeconds(), 2); // burstSize //这里实现了状态改变更新服务 statusChangeListener = new ApplicationInfoManager.StatusChangeListener() { @Override public String getId() { return "statusChangeListener"; } @Override public void notify(StatusChangeEvent statusChangeEvent) { if (InstanceStatus.DOWN == statusChangeEvent.getStatus() || InstanceStatus.DOWN == statusChangeEvent.getPreviousStatus()) { // log at warn level if DOWN was involved logger.warn("Saw local status change event {}", statusChangeEvent); } else { logger.info("Saw local status change event {}", statusChangeEvent); } instanceInfoReplicator.onDemandUpdate(); } }; //eureka.client.on-demand-update-status-change //默认为true,一般不设置成false if (clientConfig.shouldOnDemandUpdateStatusChange()) { //状态改变监听 applicationInfoManager.registerStatusChangeListener(statusChangeListener); } //开启 //初始化实例信息到Eureka服务端的间隔时间 eureka.client.initialInstanceInfoReplicationIntervalSeconds 默认40s instanceInfoReplicator.start(clientConfig.getInitialInstanceInfoReplicationIntervalSeconds()); } else { logger.info("Not registering with Eureka server per configuration"); }}
阅读全文
1 0
- eureka客户端源码解析
- Eureka 源码解析 —— Eureka-Server 集群同步
- 深入理解Eureka之源码解析
- 深入理解Eureka之源码解析
- Eureka 源码解析 —— 任务批处理
- Eureka 源码解析 —— 网络通信
- Eureka 源码解析 —— StringCache
- Eureka 源码解析 —— EndPoint 与 解析器
- ZookeeperNet客户端源码解析
- Eureka 源码解析 —— Eureka-Client 初始化(一)之 EurekaInstanceConfig
- Eureka 源码解析 —— Eureka-Client 初始化(二)之 EurekaClientConfig
- Eureka 源码解析 —— Eureka-Client 初始化(三)之 EurekaClient
- Eureka 源码解析 —— Eureka-Server 启动(一)之 ServerConfig
- Eureka 源码解析 —— Eureka-Server 启动(二)之 EurekaBootStrap
- Spring Cloud源码解析:一个注解加载Eureka client
- Spring-cloud & Netflix 源码解析:Eureka 服务注册发现接口 ****
- Eureka 源码解析 —— 项目结构简介
- Eureka 源码解析 —— 调试环境搭建
- linux下的find文件查找命令与grep文件内容查找命令
- postgresql插入后返回id
- Linux系统中挂载点的理解
- CircelView圆形头像
- 清楚浮动的方法
- eureka客户端源码解析
- android 使用Java库xstream示例
- redis-server存储与恢复
- Java中拼接两个时间
- Unity学习——Transform组件的使用(坐标系)、物体拾取投掷
- 深度解析LoRa与NB-IoT各自的特点和商业模式
- maven项目导入报错
- js从服务器读取图片属性
- C++类的特性之继承