com.alibaba.nacos.naming.core.ServiceManager Maven / Gradle / Ivy
/*
* Copyright 1999-2018 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.nacos.naming.core;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.utils.NamingUtils;
import com.alibaba.nacos.naming.cluster.ServerListManager;
import com.alibaba.nacos.naming.cluster.servers.Server;
import com.alibaba.nacos.naming.consistency.ConsistencyService;
import com.alibaba.nacos.naming.consistency.Datum;
import com.alibaba.nacos.naming.consistency.KeyBuilder;
import com.alibaba.nacos.naming.consistency.RecordListener;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeer;
import com.alibaba.nacos.naming.consistency.persistent.raft.RaftPeerSet;
import com.alibaba.nacos.naming.misc.*;
import com.alibaba.nacos.naming.push.PushService;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
/**
* Core manager storing all services in Nacos
*
* @author nkorange
*/
@Component
@DependsOn("nacosApplicationContext")
public class ServiceManager implements RecordListener {
/**
* Map>
*/
private Map> serviceMap = new ConcurrentHashMap<>();
private LinkedBlockingDeque toBeUpdatedServicesQueue = new LinkedBlockingDeque<>(1024 * 1024);
private Synchronizer synchronizer = new ServiceStatusSynchronizer();
private final Lock lock = new ReentrantLock();
@Resource(name = "consistencyDelegate")
private ConsistencyService consistencyService;
@Autowired
private SwitchDomain switchDomain;
@Autowired
private DistroMapper distroMapper;
@Autowired
private ServerListManager serverListManager;
@Autowired
private PushService pushService;
@Autowired
private RaftPeerSet raftPeerSet;
private final Object putServiceLock = new Object();
@PostConstruct
public void init() {
UtilsAndCommons.SERVICE_SYNCHRONIZATION_EXECUTOR.schedule(new ServiceReporter(), 60000, TimeUnit.MILLISECONDS);
UtilsAndCommons.SERVICE_UPDATE_EXECUTOR.submit(new UpdatedServiceProcessor());
try {
Loggers.SRV_LOG.info("listen for service meta change");
consistencyService.listen(KeyBuilder.SERVICE_META_KEY_PREFIX, this);
} catch (NacosException e) {
Loggers.SRV_LOG.error("listen for service meta change failed!");
}
}
public Map chooseServiceMap(String namespaceId) {
return serviceMap.get(namespaceId);
}
public void addUpdatedService2Queue(String namespaceId, String serviceName, String serverIP, String checksum) {
lock.lock();
try {
toBeUpdatedServicesQueue.offer(new ServiceKey(namespaceId, serviceName, serverIP, checksum), 5, TimeUnit.MILLISECONDS);
} catch (Exception e) {
toBeUpdatedServicesQueue.poll();
toBeUpdatedServicesQueue.add(new ServiceKey(namespaceId, serviceName, serverIP, checksum));
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Failed to add service to be updatd to queue.", e);
} finally {
lock.unlock();
}
}
@Override
public boolean interests(String key) {
return KeyBuilder.matchServiceMetaKey(key) && !KeyBuilder.matchSwitchKey(key);
}
@Override
public boolean matchUnlistenKey(String key) {
return KeyBuilder.matchServiceMetaKey(key) && !KeyBuilder.matchSwitchKey(key);
}
@Override
public void onChange(String key, Service service) throws Exception {
try {
if (service == null) {
Loggers.SRV_LOG.warn("received empty push from raft, key: {}", key);
return;
}
if (StringUtils.isBlank(service.getNamespaceId())) {
service.setNamespaceId(Constants.DEFAULT_NAMESPACE_ID);
}
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is changed, key: {}, value: {}", key, service);
Service oldDom = getService(service.getNamespaceId(), service.getName());
if (oldDom != null) {
oldDom.update(service);
// re-listen to handle the situation when the underlying listener is removed:
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), oldDom);
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), oldDom);
} else {
putServiceAndInit(service);
}
} catch (Throwable e) {
Loggers.SRV_LOG.error("[NACOS-SERVICE] error while processing service update", e);
}
}
@Override
public void onDelete(String key) throws Exception {
String namespace = KeyBuilder.getNamespace(key);
String name = KeyBuilder.getServiceName(key);
Service service = chooseServiceMap(namespace).get(name);
Loggers.RAFT.info("[RAFT-NOTIFIER] datum is deleted, key: {}", key);
// check again:
if (service != null && !service.allIPs().isEmpty()) {
Loggers.SRV_LOG.warn("service not empty, key: {}", key);
return;
}
if (service != null) {
service.destroy();
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, true));
consistencyService.remove(KeyBuilder.buildInstanceListKey(namespace, name, false));
consistencyService.unlisten(KeyBuilder.buildServiceMetaKey(namespace, name), service);
Loggers.SRV_LOG.info("[DEAD-SERVICE] {}", service.toJSON());
}
chooseServiceMap(namespace).remove(name);
}
private class UpdatedServiceProcessor implements Runnable {
//get changed service from other server asynchronously
@Override
public void run() {
ServiceKey serviceKey = null;
try {
while (true) {
try {
serviceKey = toBeUpdatedServicesQueue.take();
} catch (Exception e) {
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while taking item from LinkedBlockingDeque.");
}
if (serviceKey == null) {
continue;
}
GlobalExecutor.submitServiceUpdate(new ServiceUpdater(serviceKey));
}
} catch (Exception e) {
Loggers.EVT_LOG.error("[UPDATE-DOMAIN] Exception while update service: {}", serviceKey, e);
}
}
}
private class ServiceUpdater implements Runnable {
String namespaceId;
String serviceName;
String serverIP;
public ServiceUpdater(ServiceKey serviceKey) {
this.namespaceId = serviceKey.getNamespaceId();
this.serviceName = serviceKey.getServiceName();
this.serverIP = serviceKey.getServerIP();
}
@Override
public void run() {
try {
updatedHealthStatus(namespaceId, serviceName, serverIP);
} catch (Exception e) {
Loggers.SRV_LOG.warn("[DOMAIN-UPDATER] Exception while update service: {} from {}, error: {}",
serviceName, serverIP, e);
}
}
}
public int getPagedClusterState(String namespaceId, int startPage, int pageSize, String keyword, List raftPeerList) {
List matchList = new ArrayList<>();
RaftPeer localRaftPeer = raftPeerSet.local();
matchList.add(localRaftPeer);
Set otherServerSet = raftPeerSet.allServersWithoutMySelf();
if (null != otherServerSet && otherServerSet.size() > 0) {
for (String server: otherServerSet) {
String path = UtilsAndCommons.NACOS_NAMING_OPERATOR_CONTEXT + UtilsAndCommons.NACOS_NAMING_CLUSTER_CONTEXT + "/state";
Map params = Maps.newHashMapWithExpectedSize(2);
try {
String content = NamingProxy.reqCommon(path, params, server, false);
if (!StringUtils.EMPTY.equals(content)) {
RaftPeer raftPeer = JSONObject.parseObject(content, RaftPeer.class);
if (null != raftPeer) {
matchList.add(raftPeer);
}
}
} catch (Exception e) {
Loggers.SRV_LOG.warn("[QUERY-CLUSTER-STATE] Exception while query cluster state from {}, error: {}",
server, e);
}
}
}
List tempList = new ArrayList<>();
if (StringUtils.isNotBlank(keyword)) {
for (RaftPeer raftPeer : matchList) {
String ip = raftPeer.ip.split(":")[0];
if (keyword.equals(ip)) {
tempList.add(raftPeer);
}
}
matchList = tempList;
}
if (pageSize >= matchList.size()) {
raftPeerList.addAll(matchList);
return matchList.size();
}
for (int i = 0; i < matchList.size(); i++) {
if (i < startPage * pageSize) {
continue;
}
raftPeerList.add(matchList.get(i));
if (raftPeerList.size() >= pageSize) {
break;
}
}
return matchList.size();
}
public RaftPeer getMySelfClusterState() {
return raftPeerSet.local();
}
public void updatedHealthStatus(String namespaceId, String serviceName, String serverIP) {
Message msg = synchronizer.get(serverIP, UtilsAndCommons.assembleFullServiceName(namespaceId, serviceName));
JSONObject serviceJson = JSON.parseObject(msg.getData());
JSONArray ipList = serviceJson.getJSONArray("ips");
Map ipsMap = new HashMap<>(ipList.size());
for (int i = 0; i < ipList.size(); i++) {
String ip = ipList.getString(i);
String[] strings = ip.split("_");
ipsMap.put(strings[0], strings[1]);
}
Service service = getService(namespaceId, serviceName);
if (service == null) {
return;
}
boolean changed = false;
List instances = service.allIPs();
for (Instance instance : instances) {
boolean valid = Boolean.parseBoolean(ipsMap.get(instance.toIPAddr()));
if (valid != instance.isHealthy()) {
changed = true;
instance.setHealthy(valid);
Loggers.EVT_LOG.info("{} {SYNC} IP-{} : {}:{}@{}",
serviceName, (instance.isHealthy() ? "ENABLED" : "DISABLED"),
instance.getIp(), instance.getPort(), instance.getClusterName());
}
}
if (changed) {
pushService.serviceChanged(service);
}
StringBuilder stringBuilder = new StringBuilder();
List allIps = service.allIPs();
for (Instance instance : allIps) {
stringBuilder.append(instance.toIPAddr()).append("_").append(instance.isHealthy()).append(",");
}
if (changed && Loggers.EVT_LOG.isDebugEnabled()) {
Loggers.EVT_LOG.debug("[HEALTH-STATUS-UPDATED] namespace: {}, service: {}, ips: {}",
service.getNamespaceId(), service.getName(), stringBuilder.toString());
}
}
public Set getAllServiceNames(String namespaceId) {
return serviceMap.get(namespaceId).keySet();
}
public Map> getAllServiceNames() {
Map> namesMap = new HashMap<>(16);
for (String namespaceId : serviceMap.keySet()) {
namesMap.put(namespaceId, serviceMap.get(namespaceId).keySet());
}
return namesMap;
}
public Set getAllNamespaces() {
return serviceMap.keySet();
}
public List getAllServiceNameList(String namespaceId) {
if (chooseServiceMap(namespaceId) == null) {
return new ArrayList<>();
}
return new ArrayList<>(chooseServiceMap(namespaceId).keySet());
}
public Map> getResponsibleServices() {
Map> result = new HashMap<>(16);
for (String namespaceId : serviceMap.keySet()) {
result.put(namespaceId, new HashSet<>());
for (Map.Entry entry : serviceMap.get(namespaceId).entrySet()) {
Service service = entry.getValue();
if (distroMapper.responsible(entry.getKey())) {
result.get(namespaceId).add(service);
}
}
}
return result;
}
public int getResponsibleServiceCount() {
int serviceCount = 0;
for (String namespaceId : serviceMap.keySet()) {
for (Map.Entry entry : serviceMap.get(namespaceId).entrySet()) {
if (distroMapper.responsible(entry.getKey())) {
serviceCount++;
}
}
}
return serviceCount;
}
public int getResponsibleInstanceCount() {
Map> responsibleServices = getResponsibleServices();
int count = 0;
for (String namespaceId : responsibleServices.keySet()) {
for (Service service : responsibleServices.get(namespaceId)) {
count += service.allIPs().size();
}
}
return count;
}
public void easyRemoveService(String namespaceId, String serviceName) throws Exception {
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new IllegalArgumentException("specified service not exist, serviceName : " + serviceName);
}
if (!service.allIPs().isEmpty()) {
throw new IllegalArgumentException("specified service has instances, serviceName : " + serviceName);
}
consistencyService.remove(KeyBuilder.buildServiceMetaKey(namespaceId, serviceName));
}
public void addOrReplaceService(Service service) throws NacosException {
consistencyService.put(KeyBuilder.buildServiceMetaKey(service.getNamespaceId(), service.getName()), service);
}
public void createEmptyService(String namespaceId, String serviceName, boolean local) throws NacosException {
createServiceIfAbsent(namespaceId, serviceName, local, null);
}
public void createServiceIfAbsent(String namespaceId, String serviceName, boolean local, Cluster cluster) throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
Loggers.SRV_LOG.info("creating empty service {}:{}", namespaceId, serviceName);
service = new Service();
service.setName(serviceName);
service.setNamespaceId(namespaceId);
service.setGroupName(NamingUtils.getGroupName(serviceName));
// now validate the service. if failed, exception will be thrown
service.setLastModifiedMillis(System.currentTimeMillis());
service.recalculateChecksum();
if (cluster != null) {
cluster.setService(service);
service.getClusterMap().put(cluster.getName(), cluster);
}
service.validate();
putServiceAndInit(service);
if (!local) {
addOrReplaceService(service);
}
}
}
/**
* Register an instance to a service in AP mode.
*
* This method creates service or cluster silently if they don't exist.
*
* @param namespaceId id of namespace
* @param serviceName service name
* @param instance instance to register
* @throws Exception any error occurred in the process
*/
public void registerInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
createEmptyService(namespaceId, serviceName, instance.isEphemeral());
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
public void updateInstance(String namespaceId, String serviceName, Instance instance) throws NacosException {
Service service = getService(namespaceId, serviceName);
if (service == null) {
throw new NacosException(NacosException.INVALID_PARAM,
"service not found, namespace: " + namespaceId + ", service: " + serviceName);
}
if (!service.allIPs().contains(instance)) {
throw new NacosException(NacosException.INVALID_PARAM, "instance not exist: " + instance);
}
addInstance(namespaceId, serviceName, instance.isEphemeral(), instance);
}
public void addInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips) throws NacosException {
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
Service service = getService(namespaceId, serviceName);
synchronized (service) {
List instanceList = addIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
consistencyService.put(key, instances);
}
}
public void removeInstance(String namespaceId, String serviceName, boolean ephemeral, Instance... ips) throws NacosException {
Service service = getService(namespaceId, serviceName);
synchronized (service) {
removeInstance(namespaceId, serviceName, ephemeral, service, ips);
}
}
public void removeInstance(String namespaceId, String serviceName, boolean ephemeral, Service service, Instance... ips) throws NacosException {
String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);
List instanceList = substractIpAddresses(service, ephemeral, ips);
Instances instances = new Instances();
instances.setInstanceList(instanceList);
consistencyService.put(key, instances);
}
public Instance getInstance(String namespaceId, String serviceName, String cluster, String ip, int port) {
Service service = getService(namespaceId, serviceName);
if (service == null) {
return null;
}
List clusters = new ArrayList<>();
clusters.add(cluster);
List ips = service.allIPs(clusters);
if (ips == null || ips.isEmpty()) {
return null;
}
for (Instance instance : ips) {
if (instance.getIp().equals(ip) && instance.getPort() == port) {
return instance;
}
}
return null;
}
public List updateIpAddresses(Service service, String action, boolean ephemeral, Instance... ips) throws NacosException {
Datum datum = consistencyService.get(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), ephemeral));
List currentIPs = service.allIPs(ephemeral);
Map currentInstances = new HashMap<>(currentIPs.size());
Set currentInstanceIds = Sets.newHashSet();
for (Instance instance : currentIPs) {
currentInstances.put(instance.toIPAddr(), instance);
currentInstanceIds.add(instance.getInstanceId());
}
Map instanceMap;
if (datum != null) {
instanceMap = setValid(((Instances) datum.value).getInstanceList(), currentInstances);
} else {
instanceMap = new HashMap<>(ips.length);
}
for (Instance instance : ips) {
if (!service.getClusterMap().containsKey(instance.getClusterName())) {
Cluster cluster = new Cluster(instance.getClusterName(), service);
cluster.init();
service.getClusterMap().put(instance.getClusterName(), cluster);
Loggers.SRV_LOG.warn("cluster: {} not found, ip: {}, will create new cluster with default configuration.",
instance.getClusterName(), instance.toJSON());
}
if (UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE.equals(action)) {
instanceMap.remove(instance.getDatumKey());
} else {
instance.setInstanceId(instance.generateInstanceId(currentInstanceIds));
instanceMap.put(instance.getDatumKey(), instance);
}
}
if (instanceMap.size() <= 0 && UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD.equals(action)) {
throw new IllegalArgumentException("ip list can not be empty, service: " + service.getName() + ", ip list: "
+ JSON.toJSONString(instanceMap.values()));
}
return new ArrayList<>(instanceMap.values());
}
public List substractIpAddresses(Service service, boolean ephemeral, Instance... ips) throws NacosException {
return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_REMOVE, ephemeral, ips);
}
public List addIpAddresses(Service service, boolean ephemeral, Instance... ips) throws NacosException {
return updateIpAddresses(service, UtilsAndCommons.UPDATE_INSTANCE_ACTION_ADD, ephemeral, ips);
}
private Map setValid(List oldInstances, Map map) {
Map instanceMap = new HashMap<>(oldInstances.size());
for (Instance instance : oldInstances) {
Instance instance1 = map.get(instance.toIPAddr());
if (instance1 != null) {
instance.setHealthy(instance1.isHealthy());
instance.setLastBeat(instance1.getLastBeat());
}
instanceMap.put(instance.getDatumKey(), instance);
}
return instanceMap;
}
public Service getService(String namespaceId, String serviceName) {
if (serviceMap.get(namespaceId) == null) {
return null;
}
return chooseServiceMap(namespaceId).get(serviceName);
}
public boolean containService(String namespaceId, String serviceName) {
return getService(namespaceId, serviceName) != null;
}
public void putService(Service service) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
synchronized (putServiceLock) {
if (!serviceMap.containsKey(service.getNamespaceId())) {
serviceMap.put(service.getNamespaceId(), new ConcurrentHashMap<>(16));
}
}
}
serviceMap.get(service.getNamespaceId()).put(service.getName(), service);
}
private void putServiceAndInit(Service service) throws NacosException {
putService(service);
service.init();
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), true), service);
consistencyService.listen(KeyBuilder.buildInstanceListKey(service.getNamespaceId(), service.getName(), false), service);
Loggers.SRV_LOG.info("[NEW-SERVICE] {}", service.toJSON());
}
public List searchServices(String namespaceId, String regex) {
List result = new ArrayList<>();
for (Map.Entry entry : chooseServiceMap(namespaceId).entrySet()) {
Service service = entry.getValue();
String key = service.getName() + ":" + ArrayUtils.toString(service.getOwners());
if (key.matches(regex)) {
result.add(service);
}
}
return result;
}
public int getServiceCount() {
int serviceCount = 0;
for (String namespaceId : serviceMap.keySet()) {
serviceCount += serviceMap.get(namespaceId).size();
}
return serviceCount;
}
public int getInstanceCount() {
int total = 0;
for (String namespaceId : serviceMap.keySet()) {
for (Service service : serviceMap.get(namespaceId).values()) {
total += service.allIPs().size();
}
}
return total;
}
public Map getServiceMap(String namespaceId) {
return serviceMap.get(namespaceId);
}
public int getPagedService(String namespaceId, int startPage, int pageSize, String param, String containedInstance, List serviceList, boolean hasIpCount) {
List matchList;
if (chooseServiceMap(namespaceId) == null) {
return 0;
}
if (StringUtils.isNotBlank(param)) {
StringJoiner regex = new StringJoiner(Constants.SERVICE_INFO_SPLITER);
for (String s : param.split(Constants.SERVICE_INFO_SPLITER)) {
regex.add(StringUtils.isBlank(s) ? Constants.ANY_PATTERN : Constants.ANY_PATTERN + s + Constants.ANY_PATTERN);
}
matchList = searchServices(namespaceId, regex.toString());
} else {
matchList = new ArrayList<>(chooseServiceMap(namespaceId).values());
}
if (!CollectionUtils.isEmpty(matchList) && hasIpCount) {
matchList = matchList.stream().filter(s -> !CollectionUtils.isEmpty(s.allIPs())).collect(Collectors.toList());
}
if (StringUtils.isNotBlank(containedInstance)) {
boolean contained;
for (int i = 0; i < matchList.size(); i++) {
Service service = matchList.get(i);
contained = false;
List instances = service.allIPs();
for (Instance instance : instances) {
if (containedInstance.contains(":")) {
if (StringUtils.equals(instance.getIp() + ":" + instance.getPort(), containedInstance)) {
contained = true;
break;
}
} else {
if (StringUtils.equals(instance.getIp(), containedInstance)) {
contained = true;
break;
}
}
}
if (!contained) {
matchList.remove(i);
i--;
}
}
}
if (pageSize >= matchList.size()) {
serviceList.addAll(matchList);
return matchList.size();
}
for (int i = 0; i < matchList.size(); i++) {
if (i < startPage * pageSize) {
continue;
}
serviceList.add(matchList.get(i));
if (serviceList.size() >= pageSize) {
break;
}
}
return matchList.size();
}
public static class ServiceChecksum {
public String namespaceId;
public Map serviceName2Checksum = new HashMap();
public ServiceChecksum() {
this.namespaceId = Constants.DEFAULT_NAMESPACE_ID;
}
public ServiceChecksum(String namespaceId) {
this.namespaceId = namespaceId;
}
public void addItem(String serviceName, String checksum) {
if (StringUtils.isEmpty(serviceName) || StringUtils.isEmpty(checksum)) {
Loggers.SRV_LOG.warn("[DOMAIN-CHECKSUM] serviceName or checksum is empty,serviceName: {}, checksum: {}",
serviceName, checksum);
return;
}
serviceName2Checksum.put(serviceName, checksum);
}
}
private class ServiceReporter implements Runnable {
@Override
public void run() {
try {
Map> allServiceNames = getAllServiceNames();
if (allServiceNames.size() <= 0) {
//ignore
return;
}
for (String namespaceId : allServiceNames.keySet()) {
ServiceChecksum checksum = new ServiceChecksum(namespaceId);
for (String serviceName : allServiceNames.get(namespaceId)) {
if (!distroMapper.responsible(serviceName)) {
continue;
}
Service service = getService(namespaceId, serviceName);
if (service == null) {
continue;
}
service.recalculateChecksum();
checksum.addItem(serviceName, service.getChecksum());
}
Message msg = new Message();
msg.setData(JSON.toJSONString(checksum));
List sameSiteServers = serverListManager.getServers();
if (sameSiteServers == null || sameSiteServers.size() <= 0) {
return;
}
for (Server server : sameSiteServers) {
if (server.getKey().equals(NetUtils.localServer())) {
continue;
}
synchronizer.send(server.getKey(), msg);
}
}
} catch (Exception e) {
Loggers.SRV_LOG.error("[DOMAIN-STATUS] Exception while sending service status", e);
} finally {
UtilsAndCommons.SERVICE_SYNCHRONIZATION_EXECUTOR.schedule(this, switchDomain.getServiceStatusSynchronizationPeriodMillis(), TimeUnit.MILLISECONDS);
}
}
}
private static class ServiceKey {
private String namespaceId;
private String serviceName;
private String serverIP;
private String checksum;
public String getChecksum() {
return checksum;
}
public String getServerIP() {
return serverIP;
}
public String getServiceName() {
return serviceName;
}
public String getNamespaceId() {
return namespaceId;
}
public ServiceKey(String namespaceId, String serviceName, String serverIP, String checksum) {
this.namespaceId = namespaceId;
this.serviceName = serviceName;
this.serverIP = serverIP;
this.checksum = checksum;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
}