Skip to content

Commit

Permalink
fix nacos related issues (#1226)
Browse files Browse the repository at this point in the history
  • Loading branch information
chickenlj authored Aug 31, 2023
1 parent ab2e584 commit ad5a9cb
Show file tree
Hide file tree
Showing 19 changed files with 460 additions and 38 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

[中文说明](README_ZH.md)

Dubbo Admin is a console for better visualization of Dubbo services, it provides fully support for Dubbo3 and is compatible with 2.7.x, 2.6.x and 2.5.x.
Dubbo Admin is the console designed for better visualization of Dubbo services, it provides support for Dubbo3 and is compatible with 2.7.x, 2.6.x and 2.5.x.

![index](https://raw.githubusercontent.com/apache/dubbo-admin/develop/doc/images/index.png)

There are four ways to deploy Dubbo Admin to a production environment
There are four ways to deploy Dubbo Admin to a production environment.

1. [Linux with Admin](#11-linux-with-admin)
2. [Docker with Admin](#12-docker-with-admin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Map;

import static org.apache.dubbo.admin.common.util.Constants.COLON;
import static org.apache.dubbo.admin.common.util.Constants.INTERFACE_KEY;

public class SyncUtils {

Expand Down Expand Up @@ -201,7 +202,7 @@ public static <SM extends Map<String, Map<String, URL>>> Pair<String, URL> filte
}

private static String getServiceInterface(URL url) {
String serviceInterface = url.getServiceInterface();
String serviceInterface = url.getOriginalParameter(INTERFACE_KEY);
if (StringUtils.isBlank(serviceInterface) || Constants.ANY_VALUE.equals(serviceInterface)) {
serviceInterface = url.getPath();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,19 @@
import org.apache.dubbo.admin.registry.mapping.impl.NacosServiceMapping;
import org.apache.dubbo.admin.registry.mapping.impl.NoOpServiceMapping;
import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
import org.apache.dubbo.admin.registry.metadata.impl.DubboDelegateMetadataCollector;
import org.apache.dubbo.admin.registry.metadata.impl.NoOpMetadataCollector;
import org.apache.dubbo.admin.service.impl.InstanceRegistryCache;

import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.metadata.MappingListener;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.registry.RegistryFactory;
import org.apache.dubbo.registry.RegistryService;
Expand All @@ -46,6 +50,7 @@
import org.springframework.context.annotation.DependsOn;

import java.util.Arrays;
import java.util.Optional;

import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.ENABLE_EMPTY_PROTECTION_KEY;
Expand Down Expand Up @@ -181,6 +186,15 @@ MetaDataCollector getMetadataCollector() {
metaDataCollector.init();
} else {
logger.warn("you are using dubbo.registry.address, which is not recommend, please refer to: https://github.com/apache/dubbo-admin/wiki/Dubbo-Admin-configuration");
ApplicationModel applicationModel = ApplicationModel.defaultModel();
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
MetadataReportInstance metadataReportInstance = beanFactory.registerBean(MetadataReportInstance.class);

Optional<MetadataReport> metadataReport = metadataReportInstance.getMetadataReports(true)
.values().stream().findAny();

metaDataCollector = new DubboDelegateMetadataCollector(metadataReport.get());
metaDataCollector.setUrl(registryUrl);
}
return metaDataCollector;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,18 @@ public String callDubboService(CallDubboServiceRequest dubboCfg, @RequestBody Li
if (null == paramValues) {
paramValues = new Object[0];
}
CompletableFuture<Object> future = ApiDocsDubboGenericUtil.invoke(dubboCfg.getRegistryCenterUrl(), dubboCfg.getInterfaceClassName(),
dubboCfg.getMethodName(), dubboCfg.isAsync(), dubboCfg.getVersion(), paramTypes, paramValues, dubboCfg.getGroup());
try {
Object objResult = future.get();
return JSON.toJSONString(objResult, CLASS_NAME_PRE_FILTER);
} catch (InterruptedException | ExecutionException e) {
LOG.error(e.getMessage(), e);
return "Some exceptions have occurred, please check the log.";
CompletableFuture<Object> future = ApiDocsDubboGenericUtil.invoke(dubboCfg.getRegistryCenterUrl(), dubboCfg.getInterfaceClassName(),
dubboCfg.getMethodName(), dubboCfg.isAsync(), dubboCfg.getVersion(), paramTypes, paramValues, dubboCfg.getGroup());
try {
Object objResult = future.get();
return JSON.toJSONString(objResult, CLASS_NAME_PRE_FILTER);
} catch (InterruptedException | ExecutionException e) {
LOG.error(e.getMessage(), e);
return "Some exceptions have occurred, please check the log.";
}
} catch (Exception e) {
return "Error '" + e.getMessage() + "' happened when loading docs from remote. Please make sure api-docs dependency is correctly added to Dubbo providers, check the following link for more instructions: https://cn.dubbo.apache.org/zh-cn/overview/reference/admin/";
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.dubbo.admin.service.MetricsService;
import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.admin.service.impl.MetrcisCollectServiceImpl;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -102,35 +103,39 @@ public List<MetricDTO> searchService(@RequestParam String ip, @RequestParam Stri

protected void addMetricsConfigToMap(Map<String, String> configMap, String ip) {
List<Provider> providers = providerService.findByAddress(ip);
if (providers.size() > 0) {
if (!providers.isEmpty()) {
for (int i = 0; i < providers.size() && configMap.isEmpty(); i++) {
Provider provider = providers.get(i);
String service = provider.getService();
MetadataIdentifier providerIdentifier = new MetadataIdentifier(Tool.getInterface(service), Tool.getVersion(service), Tool.getGroup(service),
Constants.PROVIDER_SIDE, provider.getApplication());
String metaData = providerService.getProviderMetaData(providerIdentifier);
FullServiceDefinition providerServiceDefinition = new Gson().fromJson(metaData, FullServiceDefinition.class);
Map<String, String> parameters = providerServiceDefinition.getParameters();
String metricsPort = parameters.get(Constants.METRICS_PORT);
String metricsProtocol = parameters.get(Constants.METRICS_PROTOCOL);
if (metricsPort != null && metricsProtocol != null) {
configMap.put(metricsPort, metricsProtocol);
if (StringUtils.isNotEmpty(metaData)) {
FullServiceDefinition providerServiceDefinition = new Gson().fromJson(metaData, FullServiceDefinition.class);
Map<String, String> parameters = providerServiceDefinition.getParameters();
String metricsPort = parameters.get(Constants.METRICS_PORT);
String metricsProtocol = parameters.get(Constants.METRICS_PROTOCOL);
if (metricsPort != null && metricsProtocol != null) {
configMap.put(metricsPort, metricsProtocol);
}
}
}
} else {
List<Consumer> consumers = consumerService.findByAddress(ip);
if (consumers.size() > 0) {
if (!consumers.isEmpty()) {
for (int i = 0; i < consumers.size() && configMap.isEmpty(); i++) {
Consumer consumer = consumers.get(i);
String service = consumer.getService();
MetadataIdentifier consumerIdentifier = new MetadataIdentifier(Tool.getInterface(service), Tool.getVersion(service), Tool.getGroup(service),
Constants.CONSUMER_SIDE, consumer.getApplication());
String metaData = consumerService.getConsumerMetadata(consumerIdentifier);
Map<String, String> consumerParameters = new Gson().fromJson(metaData, Map.class);
String metricsPort = consumerParameters.get(Constants.METRICS_PORT);
String metricsProtocol = consumerParameters.get(Constants.METRICS_PROTOCOL);
if (metricsPort != null && metricsProtocol != null) {
configMap.put(metricsPort, metricsProtocol);
if (StringUtils.isNotEmpty(metaData)) {
Map<String, String> consumerParameters = new Gson().fromJson(metaData, Map.class);
String metricsPort = consumerParameters.get(Constants.METRICS_PORT);
String metricsProtocol = consumerParameters.get(Constants.METRICS_PROTOCOL);
if (metricsPort != null && metricsProtocol != null) {
configMap.put(metricsPort, metricsProtocol);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.apache.dubbo.admin.service.ProviderService;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.apache.dubbo.registry.Registry;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand All @@ -56,6 +58,9 @@ public class ServiceController {
private final ConsumerService consumerService;
private final Gson gson;

@Autowired
private Registry registry;

@Autowired
public ServiceController(ProviderService providerService, ConsumerService consumerService) {
this.providerService = providerService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,35 +18,42 @@
package org.apache.dubbo.admin.registry.mapping;

import org.apache.dubbo.admin.common.util.Constants;
import org.apache.dubbo.admin.registry.nacos.NacosData;
import org.apache.dubbo.admin.registry.nacos.NacosOpenapiUtil;
import org.apache.dubbo.admin.service.impl.InstanceRegistryCache;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.metadata.MappingChangedEvent;
import org.apache.dubbo.metadata.MappingListener;
import org.apache.dubbo.registry.client.DefaultServiceInstance;
import org.apache.dubbo.registry.client.InstanceAddressURL;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
import org.apache.dubbo.registry.nacos.NacosServiceDiscovery;

import com.google.common.collect.Sets;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

import static org.apache.dubbo.admin.common.util.Constants.CATEGORY_KEY;

public class AdminMappingListener implements MappingListener {

private static final URL CONSUMER_URL = new URL(Constants.ADMIN_PROTOCOL, NetUtils.getLocalHost(), 0, "",
Constants.INTERFACE_KEY, Constants.ANY_VALUE,
Constants.GROUP_KEY, Constants.ANY_VALUE,
Constants.VERSION_KEY, Constants.ANY_VALUE,
Constants.CLASSIFIER_KEY, Constants.ANY_VALUE,
Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + ","
CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + ","
+ Constants.CONSUMERS_CATEGORY + ","
+ Constants.ROUTERS_CATEGORY + ","
+ Constants.CONFIGURATORS_CATEGORY,
Expand Down Expand Up @@ -79,20 +86,35 @@ public void onEvent(MappingChangedEvent event) {
if (serviceInstancesChangedListener == null) {
AddressChangeListener addressChangeListener = new DefaultAddressChangeListener(serviceName, instanceRegistryCache);
serviceInstancesChangedListener = new AdminServiceInstancesChangedListener(Sets.newHashSet(serviceName), serviceDiscovery, addressChangeListener);
serviceInstancesChangedListener.setUrl(CONSUMER_URL);
// serviceInstancesChangedListener.setUrl(CONSUMER_URL);
List<ServiceInstance> allInstances = new ArrayList<>();
List<ServiceInstance> serviceInstances = serviceDiscovery.getInstances(serviceName);
if (serviceDiscovery instanceof NacosServiceDiscovery) {
List<ServiceInstance> consumerInstances = convertToInstance(NacosOpenapiUtil.getSubscribeAddressesWithHttpEndpoint(serviceDiscovery.getUrl(), serviceName));
allInstances.addAll(consumerInstances);
}
if (CollectionUtils.isNotEmpty(serviceInstances)) {
serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances));
allInstances.addAll(serviceInstances);
serviceInstancesChangedListener.onEvent(new ServiceInstancesChangedEvent(serviceName, allInstances));
}
serviceListeners.put(serviceName, serviceInstancesChangedListener);
serviceInstancesChangedListener.setUrl(CONSUMER_URL);
// serviceInstancesChangedListener.setUrl(CONSUMER_URL);
serviceDiscovery.addServiceInstancesChangedListener(serviceInstancesChangedListener);
}
}
}
}
}

private List<ServiceInstance> convertToInstance(List<NacosData> nacosData) {
return nacosData.stream().map(nacos -> {
DefaultServiceInstance instance = new DefaultServiceInstance();
instance.setHost(nacos.getIp());
instance.setPort(nacos.getPort());
return instance;
}).collect(Collectors.toList());
}

private static class DefaultAddressChangeListener implements AddressChangeListener {

private String serviceName;
Expand All @@ -107,13 +129,22 @@ public DefaultAddressChangeListener(String serviceName, InstanceRegistryCache in
@Override
public void notifyAddressChanged(String protocolServiceKey, List<URL> urls) {
String serviceKey = removeProtocol(protocolServiceKey);

ConcurrentMap<String, Map<String, List<InstanceAddressURL>>> appServiceMap = instanceRegistryCache.computeIfAbsent(Constants.PROVIDERS_CATEGORY, key -> new ConcurrentHashMap<>());

Map<String, List<InstanceAddressURL>> serviceMap = appServiceMap.computeIfAbsent(serviceName, key -> new ConcurrentHashMap<>());
Map<String, List<URL>> consumerServiceMap = instanceRegistryCache.getSubscribedCache().computeIfAbsent(serviceName, key -> new ConcurrentHashMap<>());

if (CollectionUtils.isEmpty(urls)) {
serviceMap.remove(serviceKey);
consumerServiceMap.remove(serviceKey);
} else {
List<InstanceAddressURL> instanceAddressUrls = urls.stream().map(url -> (InstanceAddressURL) url).collect(Collectors.toList());
serviceMap.put(serviceKey, instanceAddressUrls);
if ("consumer".equals(urls.get(0).getParameter(CATEGORY_KEY))) {
consumerServiceMap.put(serviceKey, urls);
} else {
List<InstanceAddressURL> instanceAddressUrls = urls.stream().map(url -> (InstanceAddressURL) url).collect(Collectors.toList());
serviceMap.put(serviceKey, instanceAddressUrls);
}
}
instanceRegistryCache.refreshConsumer(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.metadata.MappingChangedEvent;
import org.apache.dubbo.metadata.MappingListener;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper;
import org.apache.dubbo.registry.nacos.util.NacosNamingServiceUtils;

Expand All @@ -33,6 +34,10 @@
import com.alibaba.nacos.api.naming.pojo.ListView;
import com.google.common.collect.Sets;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -156,10 +161,8 @@ private void notifyMappingChangedEvent(String service) {
}
}


@Override
public void addMappingListener(MappingListener listener) {
listeners.add(listener);
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.dubbo.admin.registry.metadata.impl;

import org.apache.dubbo.admin.registry.metadata.MetaDataCollector;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.metadata.report.MetadataReport;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;

public class DubboDelegateMetadataCollector implements MetaDataCollector {
private MetadataReport metadataReport;
private URL url;

public DubboDelegateMetadataCollector(MetadataReport metadataReport) {
this.metadataReport = metadataReport;
}

@Override
public void setUrl(URL url) {
this.url = url;
}

@Override
public URL getUrl() {
return url;
}

@Override
public void init() {

}

@Override
public String getProviderMetaData(MetadataIdentifier key) {
return metadataReport.getServiceDefinition(key);
}

@Override
public String getConsumerMetaData(MetadataIdentifier key) {
return metadataReport.getServiceDefinition(key);
}
}
Loading

0 comments on commit ad5a9cb

Please sign in to comment.