diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java index f27d3af5e..0e51b623a 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/config/ConfigCenter.java @@ -25,17 +25,15 @@ 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.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; @@ -48,8 +46,8 @@ 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; import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension; @@ -169,19 +167,22 @@ Registry getRegistry() { @Bean("metaDataCollector") @DependsOn("governanceConfiguration") MetaDataCollector getMetadataCollector() { - ApplicationModel applicationModel = ApplicationModel.defaultModel(); - ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); - MetadataReportInstance metadataReportInstance = beanFactory.registerBean(MetadataReportInstance.class); - - Optional metadataReport = metadataReportInstance.getMetadataReports(true) - .values().stream().findAny(); - - if (metadataReport.isPresent()) { - return metadataReport.get()::getServiceDefinition; + MetaDataCollector metaDataCollector = new NoOpMetadataCollector(); + if (metadataUrl == null) { + if (StringUtils.isNotEmpty(metadataAddress)) { + metadataUrl = formUrl(metadataAddress, metadataGroup, metadataGroupNameSpace, username, password); + metadataUrl = metadataUrl.addParameter(CLUSTER_KEY, cluster); + } + logger.info("Admin using metadata address: " + metadataUrl); + } + if (metadataUrl != null) { + metaDataCollector = ApplicationModel.defaultModel().getExtensionLoader(MetaDataCollector.class).getExtension(metadataUrl.getProtocol()); + metaDataCollector.setUrl(metadataUrl); + metaDataCollector.init(); } else { - //NoOpMetadataCollector - return key -> null; + 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"); } + return metaDataCollector; } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java index 3d398be45..390178996 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/MetaDataCollector.java @@ -17,9 +17,20 @@ package org.apache.dubbo.admin.registry.metadata; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; +@SPI("zookeeper") public interface MetaDataCollector { - - String getMetaData(MetadataIdentifier key); + + void setUrl(URL url); + + URL getUrl(); + + void init(); + + String getProviderMetaData(MetadataIdentifier key); + + String getConsumerMetaData(MetadataIdentifier key); } diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollector.java new file mode 100644 index 000000000..7a1cbd922 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollector.java @@ -0,0 +1,84 @@ +/* + * 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 com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.Response; +import com.ecwid.consul.v1.kv.model.GetValue; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; +import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; + +import java.util.Objects; + + +public class ConsulMetaDataCollector implements MetaDataCollector { + private static final Logger LOG = LoggerFactory.getLogger(ConsulMetaDataCollector.class); + private static final int DEFAULT_PORT = 8500; + private URL url; + private ConsulClient client; + + @Override + public URL getUrl() { + return this.url; + } + + @Override + public void setUrl(URL url) { + this.url = url; + } + + @Override + public void init() { + Objects.requireNonNull(this.url, "metadataUrl require not null"); + String host = this.url.getHost(); + int port = this.url.getPort() != 0 ? url.getPort() : DEFAULT_PORT; + this.client = new ConsulClient(host, port); + } + + @Override + public String getProviderMetaData(MetadataIdentifier key) { + return doGetMetaData(key); + } + + @Override + public String getConsumerMetaData(MetadataIdentifier key) { + return doGetMetaData(key); + } + + private String doGetMetaData(MetadataIdentifier key) { + try { + Response response = this.client.getKVValue(key.getUniqueKey(KeyTypeEnum.UNIQUE_KEY)); + return response.getValue().getDecodedValue(); + } catch (Exception e) { + LOG.error(String.format("Failed to fetch metadata for %s from consul, cause: %s", + key.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), e.getMessage()), e); + } + return null; + } + + //just for test + ConsulClient getClient() { + return this.client; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java new file mode 100644 index 000000000..f03ca39d0 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NacosMetaDataCollector.java @@ -0,0 +1,123 @@ +/* + * 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 com.alibaba.nacos.api.PropertyKeyConst; +import java.util.Map; +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.StringConstantFieldValuePredicate; +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; +import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; + +import com.alibaba.nacos.api.NacosFactory; +import com.alibaba.nacos.api.config.ConfigService; +import com.alibaba.nacos.api.exception.NacosException; +import org.apache.commons.lang3.StringUtils; + +import java.util.Properties; + +import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR; +import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE; + +public class NacosMetaDataCollector implements MetaDataCollector { + private static final Logger logger = LoggerFactory.getLogger(NacosMetaDataCollector.class); + private ConfigService configService; + private String group; + private URL url; + @Override + public void setUrl(URL url) { + this.url = url; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void init() { + group = url.getParameter(Constants.GROUP_KEY, "DEFAULT_GROUP"); + configService = buildConfigService(url); + } + + private ConfigService buildConfigService(URL url) { + Properties nacosProperties = buildNacosProperties(url); + try { + configService = NacosFactory.createConfigService(nacosProperties); + } catch (NacosException e) { + if (logger.isErrorEnabled()) { + logger.error(e.getErrMsg(), e); + } + throw new IllegalStateException(e); + } + return configService; + } + + private Properties buildNacosProperties(URL url) { + Properties properties = new Properties(); + setServerAddr(url, properties); + setNamespace(url, properties); + Map parameters = url.getParameters( + StringConstantFieldValuePredicate.of(PropertyKeyConst.class)); + properties.putAll(parameters); + return properties; + } + + private void setServerAddr(URL url, Properties properties) { + + String serverAddr = url.getHost() + // Host + ":" + + url.getPort() // Port + ; + properties.put(SERVER_ADDR, serverAddr); + } + + private void setNamespace(URL url, Properties properties) { + String namespace = url.getParameter(NAMESPACE); + if (StringUtils.isNotBlank(namespace)) { + properties.put(NAMESPACE, namespace); + } + } + + @Override + public String getProviderMetaData(MetadataIdentifier key) { + return getMetaData(key); + } + + @Override + public String getConsumerMetaData(MetadataIdentifier key) { + return getMetaData(key); + } + + private String getMetaData(MetadataIdentifier identifier) { + try { + String fromDubboGroup = configService.getConfig(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), + "dubbo", 1000 * 10); + return org.apache.dubbo.common.utils.StringUtils.isNotEmpty(fromDubboGroup) ? fromDubboGroup : + configService.getConfig(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), + group, 1000 * 10); + } catch (NacosException e) { + logger.warn("Failed to get " + identifier + " from nacos, cause: " + e.getMessage(), e); + } + return null; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NoOpMetadataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NoOpMetadataCollector.java new file mode 100644 index 000000000..c6d6ad83e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/NoOpMetadataCollector.java @@ -0,0 +1,50 @@ +/* + * 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.identifier.MetadataIdentifier; + +public class NoOpMetadataCollector implements MetaDataCollector { + + @Override + public void setUrl(URL url) { + + } + + @Override + public URL getUrl() { + return null; + } + + @Override + public void init() { + + } + + @Override + public String getProviderMetaData(MetadataIdentifier key) { + return null; + } + + @Override + public String getConsumerMetaData(MetadataIdentifier key) { + return null; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/RedisMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/RedisMetaDataCollector.java new file mode 100644 index 000000000..eef341972 --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/RedisMetaDataCollector.java @@ -0,0 +1,110 @@ +/* + * 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.commons.pool2.impl.GenericObjectPoolConfig; +import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; +import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; +import org.apache.dubbo.rpc.RpcException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisCluster; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPoolConfig; + +import java.util.HashSet; +import java.util.Set; + +import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; +import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT; +import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY; +import static org.apache.dubbo.metadata.MetadataConstants.META_DATA_STORE_TAG; + +public class RedisMetaDataCollector implements MetaDataCollector { + + private final static Logger logger = LoggerFactory.getLogger(RedisMetaDataCollector.class); + private final static String REDIS_DATABASE_KEY = "database"; + private URL url; + private JedisPool pool; + Set jedisClusterNodes; + private int timeout; + private String password; + + @Override + public void setUrl(URL url) { + this.url = url; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void init() { + timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT); + password = url.getPassword(); + if (url.getParameter(CLUSTER_KEY, false)) { + jedisClusterNodes = new HashSet<>(); + String[] addresses = COMMA_SPLIT_PATTERN.split(url.getAddress()); + for (String address : addresses) { + URL tmpUrl = url.setAddress(address); + jedisClusterNodes.add(new HostAndPort(tmpUrl.getHost(), tmpUrl.getPort())); + } + } else { + int database = url.getParameter(REDIS_DATABASE_KEY, 0); + pool = new JedisPool(new JedisPoolConfig(), url.getHost(), url.getPort(), timeout, url.getPassword(), database); + } + } + + @Override + public String getProviderMetaData(MetadataIdentifier key) { + return doGetMetaData(key); + } + + @Override + public String getConsumerMetaData(MetadataIdentifier key) { + return doGetMetaData(key); + } + + private String doGetMetaData(MetadataIdentifier identifier) { + String result = null; + if (url.getParameter(CLUSTER_KEY, false)) { + try (JedisCluster jedisCluster = new JedisCluster(jedisClusterNodes, timeout, timeout, 2, password, new GenericObjectPoolConfig())) { + result = jedisCluster.get(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY) + META_DATA_STORE_TAG); + } catch (Throwable e) { + logger.error("Failed to get " + identifier + " from redis cluster, cause: " + e.getMessage(), e); + throw new RpcException("Failed to get " + identifier + " from redis cluster, cause: " + e.getMessage(), e); + } + } else { + try (Jedis jedis = pool.getResource()) { + result = jedis.get(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY)); + } catch (Throwable e) { + logger.error("Failed to get " + identifier + " from redis, cause: " + e.getMessage(), e); + throw new RpcException("Failed to get " + identifier + " from redis, cause: " + e.getMessage(), e); + } + } + return result; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java new file mode 100644 index 000000000..9bba7423e --- /dev/null +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/registry/metadata/impl/ZookeeperMetaDataCollector.java @@ -0,0 +1,103 @@ +/* + * 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.curator.framework.CuratorFramework; +import org.apache.curator.framework.CuratorFrameworkFactory; +import org.apache.curator.retry.ExponentialBackoffRetry; +import org.apache.dubbo.admin.common.util.Constants; +import org.apache.dubbo.admin.registry.metadata.MetaDataCollector; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; +import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; + +public class ZookeeperMetaDataCollector implements MetaDataCollector { + + private static final Logger logger = LoggerFactory.getLogger(ZookeeperMetaDataCollector.class); + private CuratorFramework client; + private URL url; + private String root; + private final static String DEFAULT_ROOT = "dubbo"; + + @Override + public void setUrl(URL url) { + this.url = url; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void init() { + String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT); + if (!group.startsWith(Constants.PATH_SEPARATOR)) { + group = Constants.PATH_SEPARATOR + group; + } + root = group; + CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory. + builder() + .connectString(url.getAddress()) + .retryPolicy(new ExponentialBackoffRetry(1000, 3)); + String userInformation = url.getUserInformation(); + if (userInformation != null && userInformation.length() > 0) { + builder = builder.authorization("digest", userInformation.getBytes()); + } + client = builder.build(); + client.start(); + } + + + @Override + public String getProviderMetaData(MetadataIdentifier key) { + return doGetMetadata(key); + } + + @Override + public String getConsumerMetaData(MetadataIdentifier key) { + return doGetMetadata(key); + } + + private String getNodePath(MetadataIdentifier metadataIdentifier) { + return toRootDir() + metadataIdentifier.getUniqueKey(KeyTypeEnum.PATH); + } + + private String toRootDir() { + if (root.equals(Constants.PATH_SEPARATOR)) { + return root; + } + return root + Constants.PATH_SEPARATOR; + } + + private String doGetMetadata(MetadataIdentifier identifier) { + //TODO error handing + try { + String path = getNodePath(identifier); + if (client.checkExists().forPath(path) == null) { + return null; + } + return new String(client.getData().forPath(path)); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + return null; + } +} diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java index 829330dc6..83950269d 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ConsumerServiceImpl.java @@ -55,7 +55,7 @@ public List findAll() { @Override public String getConsumerMetadata(MetadataIdentifier consumerIdentifier) { - return metaDataCollector.getMetaData(consumerIdentifier); + return metaDataCollector.getConsumerMetaData(consumerIdentifier); } private Map findAllConsumerUrl() { diff --git a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java index 81d997014..5e09ed763 100644 --- a/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java +++ b/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/ProviderServiceImpl.java @@ -59,7 +59,7 @@ public void create(Provider provider) { @Override public String getProviderMetaData(MetadataIdentifier providerIdentifier) { - return metaDataCollector.getMetaData(providerIdentifier); + return metaDataCollector.getProviderMetaData(providerIdentifier); } @Override diff --git a/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector new file mode 100644 index 000000000..fc4c85525 --- /dev/null +++ b/dubbo-admin-server/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.admin.registry.metadata.MetaDataCollector @@ -0,0 +1,4 @@ +zookeeper=org.apache.dubbo.admin.registry.metadata.impl.ZookeeperMetaDataCollector +redis=org.apache.dubbo.admin.registry.metadata.impl.RedisMetaDataCollector +consul=org.apache.dubbo.admin.registry.metadata.impl.ConsulMetaDataCollector +nacos=org.apache.dubbo.admin.registry.metadata.impl.NacosMetaDataCollector \ No newline at end of file diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/config/ConfigCenterTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/config/ConfigCenterTest.java index 53ec12ada..87271c146 100644 --- a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/config/ConfigCenterTest.java +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/config/ConfigCenterTest.java @@ -148,5 +148,10 @@ public void testGetMetadataCollector() throws Exception { ReflectionTestUtils.setField(configCenter, "metadataAddress", zkAddress + "?group=" + "dubbo"); ReflectionTestUtils.setField(configCenter, "username", "username"); ReflectionTestUtils.setField(configCenter, "password", "password"); + + configCenter.getMetadataCollector(); + Object metadataUrl = ReflectionTestUtils.getField(configCenter, "metadataUrl"); + assertNotNull(metadataUrl); + assertEquals("127.0.0.1", ((URL) metadataUrl).getHost()); } } diff --git a/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollectorTest.java b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollectorTest.java new file mode 100644 index 000000000..149539c68 --- /dev/null +++ b/dubbo-admin-server/src/test/java/org/apache/dubbo/admin/registry/metadata/impl/ConsulMetaDataCollectorTest.java @@ -0,0 +1,134 @@ +/* + * 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 com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.pszymczyk.consul.ConsulProcess; +import com.pszymczyk.consul.ConsulStarterBuilder; +import org.apache.dubbo.common.URL; +import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder; +import org.apache.dubbo.metadata.definition.model.FullServiceDefinition; +import org.apache.dubbo.metadata.definition.model.MethodDefinition; +import org.apache.dubbo.metadata.definition.util.ClassUtils; +import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; +import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; +import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; + +public class ConsulMetaDataCollectorTest { + + private final Gson gson = new Gson(); + private ConsulProcess consul; + private ConsulMetaDataCollector consulMetaDataCollector; + + @Before + public void setUp() { + consul = ConsulStarterBuilder.consulStarter().build().start(); + consulMetaDataCollector = new ConsulMetaDataCollector(); + consulMetaDataCollector.setUrl(URL.valueOf("consul://127.0.0.1:" + consul.getHttpPort())); + consulMetaDataCollector.init(); + } + + @After + public void tearDown() { + consul.close(); + consulMetaDataCollector = null; + } + + @Test + public void testGetProviderMetaData() { + MetadataIdentifier identifier = buildIdentifier(true); + + Map params = new HashMap<>(); + params.put("key1", "value1"); + params.put("key2", "true"); + + FullServiceDefinition definition = ServiceDefinitionBuilder.buildFullDefinition(ServiceA.class, params); + + String metadata = gson.toJson(definition); + consulMetaDataCollector.getClient().setKVValue(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), metadata); + + String providerMetaData = consulMetaDataCollector.getProviderMetaData(identifier); + Assert.assertEquals(metadata, providerMetaData); + + FullServiceDefinition retDef = gson.fromJson(providerMetaData, FullServiceDefinition.class); + Assert.assertEquals(ServiceA.class.getCanonicalName(), retDef.getCanonicalName()); + Assert.assertEquals(ClassUtils.getCodeSource(ServiceA.class), retDef.getCodeSource()); + Assert.assertEquals(params, retDef.getParameters()); + + //method def assertions + Assert.assertNotNull(retDef.getMethods()); + Assert.assertEquals(3, retDef.getMethods().size()); + List methodNames = retDef.getMethods().stream().map(MethodDefinition::getName).sorted().collect(Collectors.toList()); + Assert.assertEquals("method1", methodNames.get(0)); + Assert.assertEquals("method2", methodNames.get(1)); + Assert.assertEquals("method3", methodNames.get(2)); + } + + + @Test + public void testGetConsumerMetaData() { + MetadataIdentifier identifier = buildIdentifier(false); + + Map consumerParams = new HashMap<>(); + consumerParams.put("k1", "v1"); + consumerParams.put("k2", "1"); + consumerParams.put("k3", "true"); + String metadata = gson.toJson(consumerParams); + consulMetaDataCollector.getClient().setKVValue(identifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY), metadata); + + String consumerMetaData = consulMetaDataCollector.getConsumerMetaData(identifier); + Map retParams = gson.fromJson(consumerMetaData, new TypeToken>() { + }.getType()); + Assert.assertEquals(consumerParams, retParams); + } + + + private MetadataIdentifier buildIdentifier(boolean isProducer) { + MetadataIdentifier identifier = new MetadataIdentifier(); + identifier.setApplication(String.format("metadata-%s-test", isProducer ? "provider" : "consumer")); + identifier.setGroup("group"); + identifier.setServiceInterface(ServiceA.class.getName()); + identifier.setSide(isProducer ? PROVIDER_SIDE : CONSUMER_SIDE); + identifier.setVersion("1.0.0"); + return identifier; + } + + + interface ServiceA { + void method1(); + + void method2() throws IOException; + + String method3(); + } + +}