package com.dianping.pigeon.registry.composite;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.dianping.pigeon.registry.config.RegistryConfig;
import org.apache.commons.lang.StringUtils;
import com.dianping.pigeon.config.ConfigChangeListener;
import com.dianping.pigeon.config.ConfigManager;
import com.dianping.pigeon.config.ConfigManagerLoader;
import com.dianping.pigeon.extension.ExtensionLoader;
import com.dianping.pigeon.log.Logger;
import com.dianping.pigeon.log.LoggerLoader;
import com.dianping.pigeon.registry.Registry;
import com.dianping.pigeon.registry.exception.RegistryException;
import com.dianping.pigeon.registry.util.Constants;
import com.dianping.pigeon.registry.util.HeartBeatSupport;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* Created by chenchongze on 16/8/15.
*/
@Deprecated
public class CompositeRegistry implements Registry {
private final Logger logger = LoggerLoader.getLogger(getClass());
private final ConfigManager configManager = ConfigManagerLoader.getConfigManager();
private volatile List<Registry> registryList = Lists.newArrayList();
private volatile boolean inited = false;
private static final String KEY_PIGEON_REGISTRY_PREFER = "pigeon.registry.prefer";
@Override
public void init() {
if (!inited) {
synchronized (this) {
if (!inited) {
try {
String registryPreferConfig = configManager.getStringValue(KEY_PIGEON_REGISTRY_PREFER,
Constants.REGISTRY_CURATOR_NAME);
logger.info("composite registry prefer is " + registryPreferConfig);
parseRegistryConfig(registryPreferConfig);
configManager.registerConfigChangeListener(new InnerConfigChangeListener());
inited = true;
} catch (Throwable t) {
logger.error("failed to init composite registry...");
throw new RuntimeException(t);
}
}
}
}
}
@Override
public boolean isEnable() {
return inited;
}
private void parseRegistryConfig(String registryPreferConfig) {
List<Registry> _registryList = Lists.newArrayList();
for (Registry registry : ExtensionLoader.getExtensionList(Registry.class)) {
if (!registry.getName().equals(this.getName())) {
_registryList.add(registry);
}
}
Map<String, Registry> registryMapByName = Maps.newHashMap();
for (Registry registry : _registryList) {
registryMapByName.put(registry.getName(), registry);
}
List<String> registryPrefer = Arrays.asList(registryPreferConfig.split(","));
List<Registry> orderedRegistryList = Lists.newArrayList();
for (String registryName : registryPrefer) {
if (registryMapByName.containsKey(registryName)) {
orderedRegistryList.add(registryMapByName.get(registryName));
} else {
logger.error("pigeon.registry.prefer config error! no registry: " + registryName);
return;
}
}
List<Registry> candidateRegistryList = Lists.newArrayList();
for (Registry registry : orderedRegistryList) {
registry.init();
if (registry.isEnable()) {
candidateRegistryList.add(registry);
}
}
if (candidateRegistryList.size() > 0) {
registryList = candidateRegistryList;
} else {
logger.error("candidate registry num is 0! use old registry list.");
}
}
@Override
public String getName() {
return Constants.REGISTRY_COMPOSITE_NAME;
}
@Override
public String getServiceAddress(String serviceName) throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr, registry.getServiceAddress(serviceName));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public String getServiceAddress(String serviceName, String group) throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr, registry.getServiceAddress(serviceName, group));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public String getServiceAddress(String serviceName, String group, boolean fallbackDefaultGroup)
throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr, registry.getServiceAddress(serviceName, group, fallbackDefaultGroup));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public String getServiceAddress(String remoteAppkey, String serviceName, String group, boolean fallbackDefaultGroup)
throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr,
registry.getServiceAddress(remoteAppkey, serviceName, group, fallbackDefaultGroup));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public void registerService(String serviceName, String group, String serviceAddress, int weight)
throws RegistryException {
for (Registry registry : registryList) {
try {
registry.registerService(serviceName, group, serviceAddress, weight);
} catch (Throwable t) {
logger.info("failed to register service to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public void unregisterService(String serviceName, String serviceAddress) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.unregisterService(serviceName, serviceAddress);
} catch (Throwable t) {
logger.info("failed to unregister service to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public void unregisterService(String serviceName, String group, String serviceAddress) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.unregisterService(serviceName, group, serviceAddress);
} catch (Throwable t) {
logger.info("failed to unregister service to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public int getServerWeight(String serverAddress) throws RegistryException {
int weight = Constants.DEFAULT_WEIGHT;
List<Integer> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getServerWeight(serverAddress));
} catch (Throwable t) {
logger.info("failed to get weight from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get weight for " + serverAddress);
}
weight = checkValueConsistency(checkList, "weight");
return weight;
}
@Override
public List<String> getChildren(String key) throws RegistryException {
throw new RegistryException("unsupported interface in registry: " + getName());
}
@Override
public void setServerWeight(String serverAddress, int weight) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.setServerWeight(serverAddress, weight);
} catch (Throwable t) {
logger.info("failed to set weight to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public String getServerApp(String serverAddress) throws RegistryException {
String app = "";
List<String> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getServerApp(serverAddress));
} catch (Throwable t) {
logger.info("failed to get app from registry: " + registry.getName());
}
}
app = checkValueConsistency(checkList, "app");
if (app == null) {
throw new RegistryException("failed to get app for " + serverAddress);
}
return app;
}
@Override
public void setServerApp(String serverAddress, String app) {
for (Registry registry : registryList) {
try {
registry.setServerApp(serverAddress, app);
} catch (Throwable t) {
logger.info("failed to set app to registry: " + registry.getName());
}
}
}
@Override
public void unregisterServerApp(String serverAddress) {
for (Registry registry : registryList) {
try {
registry.unregisterServerApp(serverAddress);
} catch (Throwable t) {
logger.info("failed to unregister app to registry: " + registry.getName());
}
}
}
@Override
public void setServerVersion(String serverAddress, String version) {
for (Registry registry : registryList) {
try {
registry.setServerVersion(serverAddress, version);
} catch (Throwable t) {
logger.info("failed to set version to registry: " + registry.getName());
}
}
}
@Override
public String getServerVersion(String serverAddress) throws RegistryException {
String version = "";
List<String> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getServerVersion(serverAddress));
} catch (Throwable t) {
logger.info("failed to get version from registry: " + registry.getName());
}
}
version = checkValueConsistency(checkList, "version");
if (version == null) {
throw new RegistryException("failed to get version for " + serverAddress);
}
return version;
}
@Override
public void unregisterServerVersion(String serverAddress) {
for (Registry registry : registryList) {
try {
registry.unregisterServerVersion(serverAddress);
} catch (Throwable t) {
logger.info("failed to unregister version to registry: " + registry.getName());
}
}
}
@Override
public String getStatistics() {
String stats = "";
for (Registry registry : registryList) {
stats += registry.getStatistics() + ",";
}
return stats;
}
@Override
public byte getServerHeartBeatSupport(String serviceAddress) throws RegistryException {
byte support = HeartBeatSupport.BothSupport.getValue();
List<Byte> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getServerHeartBeatSupport(serviceAddress));
} catch (Throwable t) {
logger.info("failed to get heartbeat support from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get heartbeat support for " + serviceAddress);
}
support = checkValueConsistency(checkList, "server heartbeat support");
return support;
}
@Override
public Map<String, Boolean> getServiceProtocols(String serviceAddress) throws RegistryException {
Map<String, Boolean> serviceProtocols = new HashMap<String, Boolean>();
List<Map<String, Boolean>> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getServiceProtocols(serviceAddress));
} catch (Throwable t) {
logger.info("failed to get service protocols from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get service protocols for " + serviceAddress);
}
serviceProtocols = checkValueConsistency(checkList, "service protocols");
return serviceProtocols;
}
@Override
public boolean isSupportNewProtocol(String serviceAddress) throws RegistryException {
boolean support = false;
List<Boolean> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.isSupportNewProtocol(serviceAddress));
} catch (Throwable t) {
logger.info("failed to get support new protocol from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get protocol support for " + serviceAddress);
}
support = checkValueConsistency(checkList, "host protocol support");
return support;
}
@Override
public boolean isSupportNewProtocol(String serviceAddress, String serviceName) throws RegistryException {
boolean support = false;
List<Boolean> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.isSupportNewProtocol(serviceAddress, serviceName));
} catch (Throwable t) {
logger.info("failed to get support new protocol from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get service protocol support for " + serviceAddress + ", " + serviceName);
}
support = checkValueConsistency(checkList, "service protocol support");
return support;
}
@Override
public void setSupportNewProtocol(String serviceAddress, String serviceName, boolean support)
throws RegistryException {
for (Registry registry : registryList) {
try {
registry.setSupportNewProtocol(serviceAddress, serviceName, support);
} catch (Throwable t) {
logger.info("failed to set support new protocol to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public void unregisterSupportNewProtocol(String serviceAddress, String serviceName, boolean support)
throws RegistryException {
for (Registry registry : registryList) {
try {
registry.unregisterSupportNewProtocol(serviceAddress, serviceName, support);
} catch (Throwable t) {
logger.info("failed to unregister support new protocol to registry: " + registry.getName());
throw new RegistryException(t);
}
}
}
@Override
public void updateHeartBeat(String serviceAddress, Long heartBeatTimeMillis) {
for (Registry registry : registryList) {
try {
registry.updateHeartBeat(serviceAddress, heartBeatTimeMillis);
} catch (Throwable t) {
logger.info("failed to update heartbeat to registry: " + registry.getName());
}
}
}
@Override
public void deleteHeartBeat(String serviceAddress) {
for (Registry registry : registryList) {
try {
registry.deleteHeartBeat(serviceAddress);
} catch (Throwable t) {
logger.info("failed to delete heartbeat to registry: " + registry.getName());
}
}
}
@Override
public void setServerService(String serviceName, String group, String hosts) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.setServerService(serviceName, group, hosts);
} catch (Throwable t) {
logger.info("failed to set server service to registry: " + registry.getName());
}
}
}
@Override
public void delServerService(String serviceName, String group) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.delServerService(serviceName, group);
} catch (Throwable t) {
logger.info("failed to delete server service to registry: " + registry.getName());
}
}
}
@Override
public void setHostsWeight(String serviceName, String group, String hosts, int weight) throws RegistryException {
for (Registry registry : registryList) {
try {
registry.setHostsWeight(serviceName, group, hosts, weight);
} catch (Throwable t) {
logger.info("failed to set hosts weight to registry: " + registry.getName());
}
}
}
@Override
public String getServiceAddress(String remoteAppkey, String serviceName, String group, boolean fallbackDefaultGroup,
boolean needListener) throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr, registry.getServiceAddress(remoteAppkey, serviceName, group,
fallbackDefaultGroup, needListener));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public String getServiceAddress(String serviceName, String group, boolean fallbackDefaultGroup,
boolean needListener) throws RegistryException {
String addr = "";
for (Registry registry : registryList) { // merge registry addr
try {
addr = mergeAddress(addr,
registry.getServiceAddress(serviceName, group, fallbackDefaultGroup, needListener));
} catch (Throwable t) {
logger.info("failed to get service address from registry: " + registry.getName());
}
}
return addr;
}
@Override
public void setConsoleAddress(String consoleAddress) {
for (Registry registry : registryList) {
try {
registry.setConsoleAddress(consoleAddress);
} catch (Throwable t) {
logger.info("failed to set console address from registry: " + registry.getName(), t);
}
}
}
@Override
public void unregisterConsoleAddress(String consoleAddress) {
for (Registry registry : registryList) {
try {
registry.unregisterConsoleAddress(consoleAddress);
} catch (Throwable t) {
logger.info("failed to unregister console address from registry: " + registry.getName(), t);
}
}
}
@Override
public List<String> getConsoleAddresses() {
List<String> consoleAddresses = new ArrayList<String>();
for (Registry registry : registryList) {
try {
List<String> tempAddresses = registry.getConsoleAddresses();
if (tempAddresses != null && !tempAddresses.isEmpty()) {
consoleAddresses.addAll(tempAddresses);
}
} catch (Throwable t) {
logger.info("failed to get console address from registry: " + registry.getName(), t);
}
}
return consoleAddresses;
}
@Override
public RegistryConfig getRegistryConfig(String ip) throws RegistryException {
RegistryConfig registryConfig;
List<RegistryConfig> checkList = Lists.newArrayList();
for (Registry registry : registryList) {
try {
checkList.add(registry.getRegistryConfig(ip));
} catch (Throwable t) {
logger.info("failed to get registry config from registry: " + registry.getName());
}
}
if (checkList.size() == 0) {
throw new RegistryException("failed to get registry config");
}
registryConfig = checkValueConsistency(checkList, "registry config");
return registryConfig;
}
private String mergeAddress(String address, String anotherAddress) {
Set<String> result = Sets.newHashSet();
if (StringUtils.isNotBlank(address)) {
result.addAll(Arrays.asList(address.split(",")));
}
if (StringUtils.isNotBlank(anotherAddress)) {
result.addAll(Arrays.asList(anotherAddress.split(",")));
}
return StringUtils.join(result, ",");
}
private <T> T checkValueConsistency(List<T> checkList, String msg) {
T result = null;
if (checkList.size() > 0) {
result = checkList.get(0);
}
for (int i = 0; i < checkList.size(); i++) {
T t = checkList.get(i);
if (t != null && !t.equals(result)) {
String errorMsg = msg + " result not same in different registries! index0: " + result + ", index" + i
+ ": " + t;
if (configManager.getBooleanValue("pigeon.registry.check.value.consistency.exception", false)) {
throw new RuntimeException(errorMsg);
}
if (logger.isDebugEnabled()) {
logger.debug(errorMsg);
}
break;
}
}
return result;
}
private class InnerConfigChangeListener implements ConfigChangeListener {
@Override
public void onKeyUpdated(String key, String value) {
if (key.endsWith(KEY_PIGEON_REGISTRY_PREFER)) {
try {
parseRegistryConfig(value);
for (Registry registry : registryList) {
registry.init();
}
logger.info("composite registry prefer change to " + value);
} catch (Throwable t) {
logger.error(t);
}
}
}
@Override
public void onKeyAdded(String key, String value) {
}
@Override
public void onKeyRemoved(String key) {
}
}
}