diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index ef57efb4d9c3..0147c42c3ffc 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -239,6 +239,10 @@ test + + commons-net + commons-net + diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index 98aab862d288..d372f542189b 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -37,6 +37,7 @@ import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.config.utils.ConfigValidationUtils; +import org.apache.dubbo.config.utils.SubnetUtil; import org.apache.dubbo.metadata.ServiceNameMapping; import org.apache.dubbo.metrics.event.MetricsEventBus; import org.apache.dubbo.metrics.registry.event.RegistryEvent; @@ -713,9 +714,20 @@ private URL buildUrl(ProtocolConfig protocolConfig, Map params) params.put(CommonConstants.IPV6_KEY, ipv6Host); } + if (StringUtils.isBlank(getTag())) { + if (SubnetUtil.isEmpty()) { + String content = ConfigurationUtils.getCachedDynamicProperty(getScopeModel(), SubnetUtil.TAG_SUBNETS_KEY, null); + SubnetUtil.init(content); + } + if (!SubnetUtil.isEmpty()) { + String tagLevel = SubnetUtil.getTagLevelByHost(params.get(BIND_IP_KEY)); + setTag(tagLevel); + params.put(CommonConstants.TAG_KEY, tagLevel); + } + } + Integer port = findConfiguredPort(protocolConfig, provider, this.getExtensionLoader(Protocol.class), name, params); URL url = new ServiceConfigURL(name, null, null, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), params); - // You can customize Configurator to append extra parameters if (this.getExtensionLoader(ConfiguratorFactory.class) .hasExtension(url.getProtocol())) { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SubnetUtil.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SubnetUtil.java new file mode 100644 index 000000000000..85025bf729e3 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SubnetUtil.java @@ -0,0 +1,85 @@ +/* + * 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.config.utils; + +import org.apache.dubbo.common.utils.StringUtils; + +import org.apache.commons.net.util.SubnetUtils; +import org.yaml.snakeyaml.LoaderOptions; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.ReentrantReadWriteLock; + + +public class SubnetUtil { + public static final String TAG_SUBNETS_KEY = "tag.subnets"; + + private static Map> cellSubnets = new ConcurrentHashMap<>(); + protected static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + protected static final ReentrantReadWriteLock.ReadLock readLock = lock.readLock(); + protected static final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock(); + + public static boolean isEmpty() { + try { + readLock.lock(); + return cellSubnets.isEmpty(); + } finally { + readLock.unlock(); + } + } + + public static void init(String content) { + if (StringUtils.isBlank(content)) { + return; + } + try { + writeLock.lock(); + Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions())); + cellSubnets = new HashMap<>(); + Map> tmpPathSubnet = (Map>) yaml.load(content); + for (Map.Entry> entry : tmpPathSubnet.entrySet()) { + String path = entry.getKey(); + List subnetInfos = cellSubnets.computeIfAbsent(path, f -> new ArrayList()); + entry.getValue().forEach(e -> subnetInfos.add(new SubnetUtils(e.trim()).getInfo())); + } + } finally { + writeLock.unlock(); + } + } + + public static String getTagLevelByHost(String host) { + try { + readLock.lock(); + for (Map.Entry> entry : cellSubnets.entrySet()) { + for (SubnetUtils.SubnetInfo subnetInfo : entry.getValue()) { + if (subnetInfo.isInRange(host)) { + return entry.getKey(); + } + } + } + return null; + } finally { + readLock.unlock(); + } + } +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/SubnetUtilTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/SubnetUtilTest.java new file mode 100644 index 000000000000..acdd798dc84f --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/SubnetUtilTest.java @@ -0,0 +1,37 @@ +/* + * 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.config.utils; + +import org.junit.Assert; +import org.junit.Test; + + +public class SubnetUtilTest { + @Test + public void testLoadContent() { + String content = "" +// + "cn|cn-northwest|cell-1: \n" + + "- 172.37.66.0/24 #cn-northwest-1a\n" + + "cn|cn-north|cell-2: \n" + + "- 172.37.67.0/24 #cn-northwest-1b\n" + + "\"\": \n" + + "- 172.37.33.0/24 #cn-north-1a\n"; + SubnetUtil.init(content); + Assert.assertEquals(SubnetUtil.getTagLevelByHost("172.37.66.1"),"cn|cn-northwest|cell-1"); + Assert.assertEquals(SubnetUtil.getTagLevelByHost("172.37.33.1"),""); + } +} diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml index 21a83cddc3d9..fbfa053a5a45 100644 --- a/dubbo-dependencies-bom/pom.xml +++ b/dubbo-dependencies-bom/pom.xml @@ -131,6 +131,7 @@ 2.1.0 2.0 3.12.0 + 3.9.0 1.8.0 0.1.35 1.11.2 @@ -653,6 +654,11 @@ commons-lang3 ${commons_lang3_version} + + commons-net + commons-net + ${commons_net_version} + io.envoyproxy.controlplane api