本文主要研究下eureka server的RemoteRegionRegistryjava
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/registry/PeerAwareInstanceRegistryImpl.javaspring
/** * Gets the list of all {@link Applications} from the registry in sorted * lexical order of {@link Application#getName()}. * * @return the list of {@link Applications} in lexical order. */ @Override public List<Application> getSortedApplications() { List<Application> apps = new ArrayList<Application>(getApplications().getRegisteredApplications()); Collections.sort(apps, APP_COMPARATOR); return apps; }
/** * Get all applications in this instance registry, falling back to other regions if allowed in the Eureka config. * * @return the list of all known applications * * @see com.netflix.discovery.shared.LookupService#getApplications() */ public Applications getApplications() { boolean disableTransparentFallback = serverConfig.disableTransparentFallbackToOtherRegion(); if (disableTransparentFallback) { return getApplicationsFromLocalRegionOnly(); } else { return getApplicationsFromAllRemoteRegions(); // Behavior of falling back to remote region can be disabled. } }
這裏disableTransparentFallbackToOtherRegion默認爲false,即會調用getApplicationsFromAllRemoteRegionssegmentfault
/** * Returns applications including instances from all remote regions. <br/> * Same as calling {@link #getApplicationsFromMultipleRegions(String[])} with a <code>null</code> argument. */ public Applications getApplicationsFromAllRemoteRegions() { return getApplicationsFromMultipleRegions(allKnownRemoteRegions); }
注意這裏傳遞了allKnownRemoteRegions參數調用了getApplicationsFromMultipleRegionsapp
/** * This method will return applications with instances from all passed remote regions as well as the current region. * Thus, this gives a union view of instances from multiple regions. <br/> * The application instances for which this union will be done can be restricted to the names returned by * {@link EurekaServerConfig#getRemoteRegionAppWhitelist(String)} for every region. In case, there is no whitelist * defined for a region, this method will also look for a global whitelist by passing <code>null</code> to the * method {@link EurekaServerConfig#getRemoteRegionAppWhitelist(String)} <br/> * If you are not selectively requesting for a remote region, use {@link #getApplicationsFromAllRemoteRegions()} * or {@link #getApplicationsFromLocalRegionOnly()} * * @param remoteRegions The remote regions for which the instances are to be queried. The instances may be limited * by a whitelist as explained above. If <code>null</code> or empty no remote regions are * included. * * @return The applications with instances from the passed remote regions as well as local region. The instances * from remote regions can be only for certain whitelisted apps as explained above. */ public Applications getApplicationsFromMultipleRegions(String[] remoteRegions) { boolean includeRemoteRegion = null != remoteRegions && remoteRegions.length != 0; logger.debug("Fetching applications registry with remote regions: {}, Regions argument {}", includeRemoteRegion, remoteRegions); if (includeRemoteRegion) { GET_ALL_WITH_REMOTE_REGIONS_CACHE_MISS.increment(); } else { GET_ALL_CACHE_MISS.increment(); } Applications apps = new Applications(); apps.setVersion(1L); for (Entry<String, Map<String, Lease<InstanceInfo>>> entry : registry.entrySet()) { Application app = null; if (entry.getValue() != null) { for (Entry<String, Lease<InstanceInfo>> stringLeaseEntry : entry.getValue().entrySet()) { Lease<InstanceInfo> lease = stringLeaseEntry.getValue(); if (app == null) { app = new Application(lease.getHolder().getAppName()); } app.addInstance(decorateInstanceInfo(lease)); } } if (app != null) { apps.addApplication(app); } } if (includeRemoteRegion) { for (String remoteRegion : remoteRegions) { RemoteRegionRegistry remoteRegistry = regionNameVSRemoteRegistry.get(remoteRegion); if (null != remoteRegistry) { Applications remoteApps = remoteRegistry.getApplications(); for (Application application : remoteApps.getRegisteredApplications()) { if (shouldFetchFromRemoteRegistry(application.getName(), remoteRegion)) { logger.info("Application {} fetched from the remote region {}", application.getName(), remoteRegion); Application appInstanceTillNow = apps.getRegisteredApplications(application.getName()); if (appInstanceTillNow == null) { appInstanceTillNow = new Application(application.getName()); apps.addApplication(appInstanceTillNow); } for (InstanceInfo instanceInfo : application.getInstances()) { appInstanceTillNow.addInstance(instanceInfo); } } else { logger.debug("Application {} not fetched from the remote region {} as there exists a " + "whitelist and this app is not in the whitelist.", application.getName(), remoteRegion); } } } else { logger.warn("No remote registry available for the remote region {}", remoteRegion); } } } apps.setAppsHashCode(apps.getReconcileHashCode()); return apps; }
private boolean shouldFetchFromRemoteRegistry(String appName, String remoteRegion) { Set<String> whiteList = serverConfig.getRemoteRegionAppWhitelist(remoteRegion); if (null == whiteList) { whiteList = serverConfig.getRemoteRegionAppWhitelist(null); // see global whitelist. } return null == whiteList || whiteList.contains(appName); }
這裏判斷,若是對應region的AppWhitelist爲null,則以全局的白名單爲準,若是最後whiteList爲null或者whiteList包含該app,則返回true,表示須要從遠程獲取ide
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/registry/AbstractInstanceRegistry.javafetch
protected void initRemoteRegionRegistry() throws MalformedURLException { Map<String, String> remoteRegionUrlsWithName = serverConfig.getRemoteRegionUrlsWithName(); if (!remoteRegionUrlsWithName.isEmpty()) { allKnownRemoteRegions = new String[remoteRegionUrlsWithName.size()]; int remoteRegionArrayIndex = 0; for (Map.Entry<String, String> remoteRegionUrlWithName : remoteRegionUrlsWithName.entrySet()) { RemoteRegionRegistry remoteRegionRegistry = new RemoteRegionRegistry( serverConfig, clientConfig, serverCodecs, remoteRegionUrlWithName.getKey(), new URL(remoteRegionUrlWithName.getValue())); regionNameVSRemoteRegistry.put(remoteRegionUrlWithName.getKey(), remoteRegionRegistry); allKnownRemoteRegions[remoteRegionArrayIndex++] = remoteRegionUrlWithName.getKey(); } } logger.info("Finished initializing remote region registries. All known remote regions: {}", (Object) allKnownRemoteRegions); }
eureka server初始化的時候,會調用initRemoteRegionRegistry方法,它讀取remoteRegionUrlsWithName這個配置,而後新建RemoteRegionRegistry,放入regionNameVSRemoteRegistry中,另外也會記錄regionName到allKnownRemoteRegions中。 這個方法初始化了前面幾個類須要用的regionNameVSRemoteRegistry變量,及allKnownRemoteRegions變量this
eureka server的getApplications方法默認有個fallback,即會拉取remoteRegion的註冊信息到本地,若是有配置remoteRegion的話。這個的好處就是,假設服務是分不一樣region部署,若是本地region的服務實例都掛了,可是本地eureka server尚未掛,那麼它會fallback到遠程region的服務實例,提升了可用性。spa