diff --git a/changes/en-us/2.0.0.md b/changes/en-us/2.0.0.md index 0613e438deb..238c7ca1e28 100644 --- a/changes/en-us/2.0.0.md +++ b/changes/en-us/2.0.0.md @@ -25,6 +25,7 @@ The version is updated as follows: - [[#4033](https://github.com/seata/seata/pull/4033)] add SQLServer support for Server DB storage mode - [[#5717](https://github.com/seata/seata/pull/5717)] compatible with file.conf and registry.conf configurations in version 1.4.2 and below - [[#5842](https://github.com/seata/seata/pull/5842)] adding metainfo to docker image +- [[#5902](https://github.com/seata/seata/pull/5902)] support IPv6 - [[#5907](https://github.com/seata/seata/pull/5907)] support polardb-x 2.0 in AT mode ### bugfix: @@ -181,6 +182,7 @@ Thanks to these contributors for their code commits. Please report an unintended - [robynron](https://github.com/robynron) - [XQDD](https://github.com/XQDD) - [Weelerer](https://github.com/Weelerer) +- [Ifdevil](https://github.com/Ifdevil) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. diff --git a/changes/zh-cn/2.0.0.md b/changes/zh-cn/2.0.0.md index 5e01d22bee0..9ea2c10ecba 100644 --- a/changes/zh-cn/2.0.0.md +++ b/changes/zh-cn/2.0.0.md @@ -25,6 +25,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 - [[#4033](https://github.com/seata/seata/pull/4033)] 增加ServerDB存储模式的SQLServer支持 - [[#5717](https://github.com/seata/seata/pull/5717)] 兼容1.4.2及以下版本的file.conf/registry.conf配置 - [[#5842](https://github.com/seata/seata/pull/5842)] 构建docker 镜像时添加相关git信息,方便定位代码关系 +- [[#5902](https://github.com/seata/seata/pull/5902)] 支持IPv6网络环境 - [[#5907](https://github.com/seata/seata/pull/5907)] 增加AT模式的PolarDB-X 2.0数据库支持 ### bugfix: @@ -181,6 +182,7 @@ Seata 是一款开源的分布式事务解决方案,提供高性能和简单 - [robynron](https://github.com/robynron) - [XQDD](https://github.com/XQDD) - [Weelerer](https://github.com/Weelerer) +- [Ifdevil](https://github.com/Ifdevil) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 diff --git a/common/src/main/java/io/seata/common/util/NetAddressValidatorUtil.java b/common/src/main/java/io/seata/common/util/NetAddressValidatorUtil.java new file mode 100644 index 00000000000..00f8b53d90c --- /dev/null +++ b/common/src/main/java/io/seata/common/util/NetAddressValidatorUtil.java @@ -0,0 +1,152 @@ +/* + * Copyright 1999-2019 Seata.io Group. + * + * 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 io.seata.common.util; + +import java.util.regex.Pattern; + +/** + * ipv4 ipv6 check util. + * + * @author Ifdevil + */ +public class NetAddressValidatorUtil { + + private static final String PERCENT = "%"; + + private static final String DOUBLE_COLON = "::"; + + private static final String DOUBLE_COLON_FFFF = "::ffff:"; + + private static final String FE80 = "fe80:"; + + private static final int ZERO = 0; + + private static final int SEVEN = 7; + + private static final int FIVE = 5; + + private static final Pattern IPV4_PATTERN = Pattern + .compile("^" + "(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)" + "(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}" + "$"); + + private static final Pattern IPV6_STD_PATTERN = Pattern + .compile("^" + "(?:[0-9a-fA-F]{1,4}:){7}" + "[0-9a-fA-F]{1,4}" + "$"); + + private static final Pattern IPV6_HEX_COMPRESSED_PATTERN = Pattern + .compile("^" + "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "::" + + + "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "$"); + + private static final Pattern IPV6_MIXED_COMPRESSED_REGEX = Pattern.compile( + "^" + "(" + "(?:[0-9A-Fa-f]{1,4}" + "(?::[0-9A-Fa-f]{1,4})*)?" + ")" + "::" + "(" + "(?:[0-9A-Fa-f]{1,4}:" + + "(?:[0-9A-Fa-f]{1,4}:)*)?" + ")" + "$"); + + private static final Pattern IPV6_MIXED_UNCOMPRESSED_REGEX = Pattern + .compile("^" + "(?:[0-9a-fA-F]{1,4}:){6}" + "$"); + + + public static boolean isIPv4Address(final String input) { + return IPV4_PATTERN.matcher(input).matches(); + } + + public static boolean isIPv6Address(final String input) { + return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input) || isLinkLocalIPv6WithZoneIndex(input) + || isIPv6IPv4MappedAddress(input) || isIPv6MixedAddress(input); + } + + /** + * Check if the given address is a valid IPv6 address in the standard format + * The format is 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. Eight blocks of hexadecimal digits + * are required. + * + * @param input ip-address to check + * @return true if input is in correct IPv6 notation. + */ + public static boolean isIPv6StdAddress(final String input) { + return IPV6_STD_PATTERN.matcher(input).matches(); + } + + /** + * Check if the given address is a valid IPv6 address in the hex-compressed notation + * The format is 'xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'. If all digits in a block are '0' + * the block can be left empty. + * + * @param input ip-address to check + * @return true if input is in correct IPv6 (hex-compressed) notation. + */ + public static boolean isIPv6HexCompressedAddress(final String input) { + return IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches(); + } + + /** + * Check if the given address is a valid IPv6 address in the mixed-standard or mixed-compressed notation. + * IPV6 Mixed mode consists of two parts, the first 96 bits (up to 6 blocks of 4 hex digits) are IPv6 + * the IPV6 part can be either compressed or uncompressed + * the second block is a full IPv4 address + * e.g. '0:0:0:0:0:0:172.12.55.18' + * + * @param input ip-address to check + * @return true if input is in correct IPv6 (mixed-standard or mixed-compressed) notation. + */ + public static boolean isIPv6MixedAddress(final String input) { + int splitIndex = input.lastIndexOf(':'); + if (splitIndex == -1) { + return false; + } + //the last part is a ipv4 address + boolean ipv4PartValid = isIPv4Address(input.substring(splitIndex + 1)); + String ipV6Part = input.substring(ZERO, splitIndex + 1); + if (DOUBLE_COLON.equals(ipV6Part)) { + return ipv4PartValid; + } + boolean ipV6UncompressedDetected = IPV6_MIXED_UNCOMPRESSED_REGEX.matcher(ipV6Part).matches(); + boolean ipV6CompressedDetected = IPV6_MIXED_COMPRESSED_REGEX.matcher(ipV6Part).matches(); + return ipv4PartValid && (ipV6UncompressedDetected || ipV6CompressedDetected); + } + + /** + * Check if input is an IPv4 address mapped into a IPv6 address. These are + * starting with "::ffff:" followed by the IPv4 address in a dot-seperated notation. + * The format is '::ffff:d.d.d.d' + * + * @param input ip-address to check + * @return true if input is in correct IPv6 notation containing an IPv4 address + */ + public static boolean isIPv6IPv4MappedAddress(final String input) { + if (input.length() > SEVEN && input.substring(ZERO, SEVEN).equalsIgnoreCase(DOUBLE_COLON_FFFF)) { + String lowerPart = input.substring(SEVEN); + return isIPv4Address(lowerPart); + } + return false; + } + + /** + * Check if input is a link local IPv6 address starting with "fe80:" and containing + * a zone index with "%xxx". The zone index will not be checked. + * + * @param input ip-address to check + * @return true if address part of input is in correct IPv6 notation. + */ + public static boolean isLinkLocalIPv6WithZoneIndex(String input) { + if (input.length() > FIVE && input.substring(ZERO, FIVE).equalsIgnoreCase(FE80)) { + int lastIndex = input.lastIndexOf(PERCENT); + if (lastIndex > ZERO && lastIndex < (input.length() - 1)) { + String ipPart = input.substring(ZERO, lastIndex); + return isIPv6StdAddress(ipPart) || isIPv6HexCompressedAddress(ipPart); + } + } + return false; + } +} diff --git a/common/src/main/java/io/seata/common/util/NetUtil.java b/common/src/main/java/io/seata/common/util/NetUtil.java index a5decf5c970..4feb47d1b7c 100644 --- a/common/src/main/java/io/seata/common/util/NetUtil.java +++ b/common/src/main/java/io/seata/common/util/NetUtil.java @@ -15,17 +15,22 @@ */ package io.seata.common.util; +import io.seata.common.Constants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.NetworkInterface; import java.net.SocketAddress; import java.net.UnknownHostException; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; -import java.util.regex.Pattern; +import java.util.LinkedHashSet; +import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * The type Net util. @@ -34,13 +39,25 @@ */ public class NetUtil { private static final Logger LOGGER = LoggerFactory.getLogger(NetUtil.class); - private static final String LOCALHOST = "127.0.0.1"; + public static final boolean PREFER_IPV6_ADDRESSES = Boolean.parseBoolean( + System.getProperty("java.net.preferIPv6Addresses")); + + private static final String LOCALHOST = "127.0.0.1"; private static final String ANY_HOST = "0.0.0.0"; + public static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1"; + public static final String LOCALHOST_SHORT_IPV6 = "::1"; + public static final String ANY_HOST_IPV6 = "0:0:0:0:0:0:0:0"; + public static final String ANY_HOST_SHORT_IPV6 = "::"; + private static volatile InetAddress LOCAL_ADDRESS = null; - private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); + private static final Set FORBIDDEN_HOSTS = Collections.unmodifiableSet( + new LinkedHashSet<>(Arrays.asList( + LOCALHOST, ANY_HOST, + LOCALHOST_IPV6, LOCALHOST_SHORT_IPV6, + ANY_HOST_IPV6,ANY_HOST_SHORT_IPV6))); /** * To string address string. @@ -83,12 +100,12 @@ public static String toStringAddress(InetSocketAddress address) { * @return the inet socket address */ public static InetSocketAddress toInetSocketAddress(String address) { - int i = address.indexOf(':'); + String[] ipPortStr = splitIPPortStr(address); String host; int port; - if (i > -1) { - host = address.substring(0, i); - port = Integer.parseInt(address.substring(i + 1)); + if (null != ipPortStr) { + host = ipPortStr[0]; + port = Integer.parseInt(ipPortStr[1]); } else { host = address; port = 0; @@ -96,6 +113,27 @@ public static InetSocketAddress toInetSocketAddress(String address) { return new InetSocketAddress(host, port); } + public static String[] splitIPPortStr(String address) { + if (StringUtils.isBlank(address)) { + throw new IllegalArgumentException("ip and port string cannot be empty!"); + } + if (address.charAt(0) == '[') { + address = removeBrackets(address); + } + String[] serverAddArr = null; + int i = address.lastIndexOf(Constants.IP_PORT_SPLIT_CHAR); + if (i > -1) { + serverAddArr = new String[2]; + String hostAddress = address.substring(0,i); + if (hostAddress.contains("%")) { + hostAddress = hostAddress.substring(0, hostAddress.indexOf("%")); + } + serverAddArr[0] = hostAddress; + serverAddArr[1] = address.substring(i + 1); + } + return serverAddArr; + } + /** * To long long. * @@ -121,7 +159,23 @@ public static long toLong(String address) { */ public static String getLocalIp(String... preferredNetworks) { InetAddress address = getLocalAddress(preferredNetworks); - return address == null ? LOCALHOST : address.getHostAddress(); + if (null != address) { + String hostAddress = address.getHostAddress(); + if (address instanceof Inet6Address) { + if (hostAddress.contains("%")) { + hostAddress = hostAddress.substring(0, hostAddress.indexOf("%")); + } + } + return hostAddress; + } + return localIP(); + } + + public static String localIP() { + if (PREFER_IPV6_ADDRESSES) { + return LOCALHOST_IPV6; + } + return LOCALHOST; } /** @@ -224,7 +278,21 @@ private static boolean isValidAddress(InetAddress address) { if (address == null || address.isLoopbackAddress()) { return false; } - return isValidIp(address.getHostAddress(), false); + String hostAddress = address.getHostAddress(); + if (address instanceof Inet6Address) { + if (!PREFER_IPV6_ADDRESSES) { + return false; + } + if (address.isAnyLocalAddress() // filter ::/128 + || address.isLinkLocalAddress() //filter fe80::/10 + || address.isSiteLocalAddress()// filter fec0::/10 + || isUniqueLocalAddress(address)) //filter fd00::/8 + { + return false; + } + return isValidIPv6(hostAddress); + } + return !FORBIDDEN_HOSTS.contains(hostAddress) && isValidIPv4(hostAddress); } /** @@ -240,11 +308,10 @@ public static boolean isValidIp(String ip, boolean validLocalAndAny) { } ip = convertIpIfNecessary(ip); if (validLocalAndAny) { - return IP_PATTERN.matcher(ip).matches(); + return isValidIPv4(ip) || isValidIPv6(ip); } else { - return !ANY_HOST.equals(ip) && !LOCALHOST.equals(ip) && IP_PATTERN.matcher(ip).matches(); + return !FORBIDDEN_HOSTS.contains(ip) && (isValidIPv4(ip) || isValidIPv6(ip)); } - } /** @@ -254,7 +321,7 @@ public static boolean isValidIp(String ip, boolean validLocalAndAny) { * @return java.lang.String */ private static String convertIpIfNecessary(String ip) { - if (IP_PATTERN.matcher(ip).matches()) { + if (isValidIPv4(ip) || isValidIPv6(ip)) { return ip; } else { try { @@ -264,4 +331,24 @@ private static String convertIpIfNecessary(String ip) { } } } + + public static boolean isValidIPv4(String ip) { + return NetAddressValidatorUtil.isIPv4Address(ip); + } + + public static boolean isValidIPv6(String ip) { + return NetAddressValidatorUtil.isIPv6Address(ip); + } + + private static boolean isUniqueLocalAddress(InetAddress address) { + byte[] ip = address.getAddress(); + return (ip[0] & 0xff) == 0xfd; + } + + private static String removeBrackets(String str) { + if (StringUtils.isBlank(str)) { + return ""; + } + return str.replaceAll("[\\[\\]]", ""); + } } diff --git a/common/src/test/java/io/seata/common/util/NetAddressValidatorUtilTest.java b/common/src/test/java/io/seata/common/util/NetAddressValidatorUtilTest.java new file mode 100644 index 00000000000..b274855cf1f --- /dev/null +++ b/common/src/test/java/io/seata/common/util/NetAddressValidatorUtilTest.java @@ -0,0 +1,56 @@ +package io.seata.common.util; + +/* + * Copyright 1999-2019 Seata.io Group. + * + * 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. + */ +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * The Net Validator util test. + * + * @author Ifdevil + */ +public class NetAddressValidatorUtilTest { + + @Test + public void isIPv6Address() { + assertThat(NetAddressValidatorUtil.isIPv6Address("2000:0000:0000:0000:0001:2345:6789:abcd")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv6Address("2001:DB8:0:0:8:800:200C:417A")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv6Address("2001:DB8::8:800:200C:417A")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv6Address("2001:DB8::8:800:200C141aA")).isFalse(); + assertThat(NetAddressValidatorUtil.isIPv6Address("::")).isTrue(); + } + + @Test + public void isIPv6MixedAddress() { + assertThat(NetAddressValidatorUtil.isIPv6MixedAddress("1:0:0:0:0:0:172.12.55.18")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv6MixedAddress("2001:DB8::8:800:200C141aA")).isFalse(); + } + + @Test + public void isIPv6IPv4MappedAddress() { + assertThat(NetAddressValidatorUtil.isIPv6IPv4MappedAddress(":ffff:1.1.1.1")).isFalse(); + assertThat(NetAddressValidatorUtil.isIPv6IPv4MappedAddress("::FFFF:192.168.1.2")).isTrue(); + } + + @Test + public void isIPv4Address() { + assertThat(NetAddressValidatorUtil.isIPv4Address("192.168.1.2")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv4Address("127.0.0.1")).isTrue(); + assertThat(NetAddressValidatorUtil.isIPv4Address("999.999.999.999")).isFalse(); + } +} diff --git a/common/src/test/java/io/seata/common/util/NetUtilTest.java b/common/src/test/java/io/seata/common/util/NetUtilTest.java index c830e0fc892..ba3f2c75aaf 100644 --- a/common/src/test/java/io/seata/common/util/NetUtilTest.java +++ b/common/src/test/java/io/seata/common/util/NetUtilTest.java @@ -181,4 +181,20 @@ public void testIsValidIp() { } + @Test + public void testSplitIPPortStr() { + String[] ipPort = new String[]{"127.0.0.1","8080"}; + assertThat(NetUtil.splitIPPortStr("127.0.0.1:8080")).isEqualTo(ipPort); + ipPort = new String[]{"::","8080"}; + assertThat(NetUtil.splitIPPortStr("[::]:8080")).isEqualTo(ipPort); + ipPort = new String[]{"2000:0000:0000:0000:0001:2345:6789:abcd","8080"}; + assertThat(NetUtil.splitIPPortStr("2000:0000:0000:0000:0001:2345:6789:abcd%10:8080")).isEqualTo(ipPort); + ipPort = new String[]{"2000:0000:0000:0000:0001:2345:6789:abcd","8080"}; + assertThat(NetUtil.splitIPPortStr("[2000:0000:0000:0000:0001:2345:6789:abcd]:8080")).isEqualTo(ipPort); + ipPort = new String[]{"::FFFF:192.168.1.2","8080"}; + assertThat(NetUtil.splitIPPortStr("::FFFF:192.168.1.2:8080")).isEqualTo(ipPort); + ipPort = new String[]{"::FFFF:192.168.1.2","8080"}; + assertThat(NetUtil.splitIPPortStr("[::FFFF:192.168.1.2]:8080")).isEqualTo(ipPort); + } + } diff --git a/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java index 33e39033e95..49bd6b12d9c 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/ChannelManager.java @@ -19,6 +19,7 @@ import io.seata.common.Constants; import io.seata.common.exception.FrameworkException; import io.seata.common.util.CollectionUtils; +import io.seata.common.util.NetUtil; import io.seata.common.util.StringUtils; import io.seata.core.protocol.IncompatibleVersionException; import io.seata.core.protocol.RegisterRMRequest; @@ -97,7 +98,16 @@ private static String buildClientId(String applicationId, Channel channel) { } private static String[] readClientId(String clientId) { - return clientId.split(Constants.CLIENT_ID_SPLIT_CHAR); + int i = clientId.indexOf(Constants.CLIENT_ID_SPLIT_CHAR); + String[] clientIdInfo = null; + if (i > -1) { + String applicationId = clientId.substring(0, i); + String[] ipPortStr = NetUtil.splitIPPortStr(clientId.substring(i + 1)); + if (null != ipPortStr && ipPortStr.length == 2) { + clientIdInfo = new String[]{applicationId, ipPortStr[0], ipPortStr[1]}; + } + } + return clientIdInfo; } private static RpcContext buildChannelHolder(NettyPoolKey.TransactionRole clientRole, String version, String applicationId, diff --git a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java index d93de7a2bde..8de294551a1 100644 --- a/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java +++ b/core/src/main/java/io/seata/core/rpc/netty/NettyClientChannelManager.java @@ -205,7 +205,7 @@ void reconnect(String transactionServiceGroup) { if (CollectionUtils.isNotEmpty(channelAddress)) { List aliveAddress = new ArrayList<>(channelAddress.size()); for (String address : channelAddress) { - String[] array = address.split(":"); + String[] array = NetUtil.splitIPPortStr(address); aliveAddress.add(new InetSocketAddress(array[0], Integer.parseInt(array[1]))); } RegistryFactory.getInstance().refreshAliveLookup(transactionServiceGroup, aliveAddress); diff --git a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java index 4f4fa0840f8..8daad242736 100644 --- a/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java +++ b/discovery/seata-discovery-core/src/main/java/io/seata/discovery/registry/FileRegistryServiceImpl.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; +import io.seata.common.util.NetUtil; import io.seata.common.util.StringUtils; import io.seata.config.ConfigChangeListener; import io.seata.config.Configuration; @@ -88,7 +89,7 @@ public List lookup(String key) throws Exception { String[] endpoints = endpointStr.split(ENDPOINT_SPLIT_CHAR); List inetSocketAddresses = new ArrayList<>(); for (String endpoint : endpoints) { - String[] ipAndPort = endpoint.split(IP_PORT_SPLIT_CHAR); + String[] ipAndPort = NetUtil.splitIPPortStr(endpoint); if (ipAndPort.length != 2) { throw new IllegalArgumentException("endpoint format should like ip:port"); } diff --git a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java index b2bc4b1858e..4330e9d6bda 100644 --- a/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java +++ b/discovery/seata-discovery-etcd3/src/main/java/io/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java @@ -248,7 +248,7 @@ private void refreshCluster(String cluster) throws Exception { GetResponse getResponse = getClient().getKVClient().get(buildRegistryKeyPrefix(cluster), getOption).get(); //2.add to list List instanceList = getResponse.getKvs().stream().map(keyValue -> { - String[] instanceInfo = keyValue.getValue().toString(UTF_8).split(":"); + String[] instanceInfo = NetUtil.splitIPPortStr(keyValue.getValue().toString(UTF_8)); return new InetSocketAddress(instanceInfo[0], Integer.parseInt(instanceInfo[1])); }).collect(Collectors.toList()); clusterAddressMap.put(cluster, new Pair<>(getResponse.getHeader().getRevision(), instanceList)); diff --git a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java index 1a0363c70d5..336037f8c9d 100644 --- a/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java +++ b/discovery/seata-discovery-redis/src/main/java/io/seata/discovery/registry/redis/RedisRegistryServiceImpl.java @@ -84,7 +84,7 @@ private RedisRegistryServiceImpl() { this.clusterName = seataConfig.getConfig(REDIS_FILEKEY_PREFIX + REGISTRY_CLUSTER_KEY, DEFAULT_CLUSTER); String password = seataConfig.getConfig(getRedisPasswordFileKey()); String serverAddr = seataConfig.getConfig(getRedisAddrFileKey()); - String[] serverArr = serverAddr.split(":"); + String[] serverArr = NetUtil.splitIPPortStr(serverAddr); String host = serverArr[0]; int port = Integer.parseInt(serverArr[1]); int db = seataConfig.getInt(getRedisDbFileKey()); diff --git a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java index 28105f390c7..a5011638214 100644 --- a/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java +++ b/discovery/seata-discovery-sofa/src/main/java/io/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java @@ -190,8 +190,8 @@ private List flatData(Map> instances) { for (Map.Entry> entry : instances.entrySet()) { for (String str : entry.getValue()) { - String ip = StringUtils.substringBefore(str, HOST_SEPERATOR); - String port = StringUtils.substringAfter(str, HOST_SEPERATOR); + String ip = StringUtils.substringBeforeLast(str, HOST_SEPERATOR); + String port = StringUtils.substringAfterLast(str, HOST_SEPERATOR); InetSocketAddress inetSocketAddress = new InetSocketAddress(ip, Integer.parseInt(port)); result.add(inetSocketAddress); } diff --git a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java index 24344d196ec..fe2613a5fde 100644 --- a/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java +++ b/discovery/seata-discovery-zk/src/main/java/io/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java @@ -42,8 +42,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static io.seata.common.Constants.IP_PORT_SPLIT_CHAR; - /** * zookeeper path as /registry/zk/ * @@ -303,7 +301,7 @@ private void refreshClusterAddressMap(String clusterName, List instances } for (String path : instances) { try { - String[] ipAndPort = path.split(IP_PORT_SPLIT_CHAR); + String[] ipAndPort = NetUtil.splitIPPortStr(path); newAddressList.add(new InetSocketAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1]))); } catch (Exception e) { LOGGER.warn("The cluster instance info is error, instance info:{}", path);