開啓eureka client的註解@EnableDiscoveryClient的功能類DiscoveryClient梳理圖
獲取server url位於類EndpointUtils的getServiceUrlsMapFromConfig方法上
public static Map<String, List<String>> getServiceUrlsMapFromConfig(EurekaClientConfig clientConfig, String instanceZone, boolean preferSameZone) { Map<String, List<String>> orderedUrls = new LinkedHashMap(); //獲取regin,一個微服務應用只有一個region String region = getRegion(clientConfig); //獲取zone,一個微服務能夠有多個zone String[] availZones = clientConfig.getAvailabilityZones(clientConfig.getRegion()); if (availZones == null || availZones.length == 0) { //若是zone爲null,就設置爲default availZones = new String[]{"default"}; } logger.debug("The availability zone for the given region {} are {}", region, Arrays.toString(availZones)); int myZoneOffset = getZoneOffset(instanceZone, preferSameZone, availZones); String zone = availZones[myZoneOffset]; //根據region和zone得出server url, 而且能夠配置多個server url List<String> serviceUrls = clientConfig.getEurekaServerServiceUrls(zone); if (serviceUrls != null) { orderedUrls.put(zone, serviceUrls); } int currentOffset = myZoneOffset == availZones.length - 1 ? 0 : myZoneOffset + 1; while(currentOffset != myZoneOffset) { zone = availZones[currentOffset]; serviceUrls = clientConfig.getEurekaServerServiceUrls(zone); if (serviceUrls != null) { orderedUrls.put(zone, serviceUrls); } if (currentOffset == availZones.length - 1) { currentOffset = 0; } else { ++currentOffset; } } if (orderedUrls.size() < 1) { throw new IllegalArgumentException("DiscoveryClient: invalid serviceUrl specified!"); } else { return orderedUrls; } }
服務註冊DiscoveryClient initScheduledTasks方法
private void initScheduledTasks() { int renewalIntervalInSecs; int expBackOffBound; if (this.clientConfig.shouldFetchRegistry()) { renewalIntervalInSecs = this.clientConfig.getRegistryFetchIntervalSeconds(); expBackOffBound = this.clientConfig.getCacheRefreshExecutorExponentialBackOffBound(); this.scheduler.schedule(new TimedSupervisorTask("cacheRefresh", this.scheduler, this.cacheRefreshExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.CacheRefreshThread()), (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.scheduler.schedule(new TimedSupervisorTask("heartbeat", this.scheduler, this.heartbeatExecutor, renewalIntervalInSecs, TimeUnit.SECONDS, expBackOffBound, new DiscoveryClient.HeartbeatThread()), (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"); } }
上面代碼中 this.instanceInfoReplicator.start(this.clientConfig.getInitialInstanceInfoReplicationIntervalSeconds());開啓了一個任務,該任務的代碼以下app
public void run() { boolean var6 = false; ScheduledFuture next; label53: { try { var6 = true; this.discoveryClient.refreshInstanceInfo(); Long dirtyTimestamp = this.instanceInfo.isDirtyWithTime(); if (dirtyTimestamp != null) { //真正觸發了註冊 this.discoveryClient.register(); this.instanceInfo.unsetIsDirty(dirtyTimestamp); var6 = false; } else { var6 = false; } break label53; } catch (Throwable var7) { logger.warn("There was a problem with the instance info replicator", var7); var6 = false; } finally { if (var6) { ScheduledFuture next = this.scheduler.schedule(this, (long)this.replicationIntervalSeconds, TimeUnit.SECONDS); this.scheduledPeriodicRef.set(next); } } next = this.scheduler.schedule(this, (long)this.replicationIntervalSeconds, TimeUnit.SECONDS); this.scheduledPeriodicRef.set(next); return; } next = this.scheduler.schedule(this, (long)this.replicationIntervalSeconds, TimeUnit.SECONDS); this.scheduledPeriodicRef.set(next); }
真正觸發了註冊的代碼爲this.discoveryClient.register(); 註冊的代碼爲:微服務
boolean register() throws Throwable { logger.info("DiscoveryClient_" + this.appPathIdentifier + ": registering service..."); EurekaHttpResponse httpResponse; try { //經過REST請求進行註冊 httpResponse = this.eurekaTransport.registrationClient.register(this.instanceInfo); } catch (Exception var3) { logger.warn("{} - registration failed {}", new Object[]{"DiscoveryClient_" + this.appPathIdentifier, var3.getMessage(), var3}); throw var3; } if (logger.isInfoEnabled()) { logger.info("{} - registration status: {}", "DiscoveryClient_" + this.appPathIdentifier, httpResponse.getStatusCode()); } return httpResponse.getStatusCode() == 204; }