序
本文主要研究下eureka server的RemoteRegionRegistry
PeerAwareInstanceRegistryImpl.getSortedApplications
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/registry/PeerAwareInstanceRegistryImpl.java
/**
* 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;
}
getApplications
/**
* 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,即会调用getApplicationsFromAllRemoteRegions
getApplicationsFromAllRemoteRegions
/**
* 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参数调用了getApplicationsFromMultipleRegions
getApplicationsFromMultipleRegions
/**
* 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;
}
- 这里会再对remoteRegions参数进行校验,确定是否includeRemoteRegion
- 首先从本地的registry获取applications
- 如果includeRemoteRegion为true的话,则在判断从regionNameVSRemoteRegistry获取指定region的RemoteRegionRegistry是否为null
- 另外还有shouldFetchFromRemoteRegistry(application.getName(), remoteRegion)判断,如果需要获取,则往apps结果集添加远程registry的注册信息
shouldFetchFromRemoteRegistry(application.getName(), remoteRegion)
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,表示需要从远程获取
AbstractInstanceRegistry.initRemoteRegionRegistry
eureka-core-1.8.8-sources.jar!/com/netflix/eureka/registry/AbstractInstanceRegistry.java
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变量
小结
eureka server的getApplications方法默认有个fallback,即会拉取remoteRegion的注册信息到本地,如果有配置remoteRegion的话。这个的好处就是,假设服务是分不同region部署,如果本地region的服务实例都挂了,但是本地eureka server还没有挂,那么它会fallback到远程region的服务实例,提高了可用性。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。