diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java
index 0b0d27a90..8bb7e3d2b 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/NacosDiscoveryProperties.java
@@ -17,6 +17,8 @@
package com.alibaba.cloud.nacos;
import java.net.Inet4Address;
+
+import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
@@ -30,6 +32,7 @@ import java.util.regex.Pattern;
import javax.annotation.PostConstruct;
import com.alibaba.cloud.nacos.event.NacosDiscoveryInfoChangedEvent;
+import com.alibaba.cloud.nacos.intetuntil.InetIPv6Utils;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.PreservedMetadataKeys;
import com.alibaba.nacos.client.naming.utils.UtilAndComs;
@@ -60,6 +63,7 @@ import static com.alibaba.nacos.api.PropertyKeyConst.USERNAME;
/**
* @author dungu.zpf
* @author xiaojing
+ * @author HH
* @author Mercy
* @author lyuzb
* @author eshun
@@ -161,6 +165,11 @@ public class NacosDiscoveryProperties {
*/
private String networkInterface = "";
+ /**
+ * choose IPV4 or IPV6,if you don't set it will choose IPV4
+ */
+ private String ipType = "IPv4" ;
+
/**
* The port your want to register for your service instance, needn't to set it if the
* auto detect port works well.
@@ -213,6 +222,9 @@ public class NacosDiscoveryProperties {
*/
private boolean failFast = true;
+ @Autowired
+ private InetIPv6Utils inetIPUtils;
+
@Autowired
private InetUtils inetUtils;
@@ -244,7 +256,17 @@ public class NacosDiscoveryProperties {
if (StringUtils.isEmpty(ip)) {
// traversing network interfaces if didn't specify a interface
if (StringUtils.isEmpty(networkInterface)) {
- ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
+ if (ipType.equalsIgnoreCase("IPv4")){
+ ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
+ }else if (ipType.equalsIgnoreCase("IPv6")){
+ ip = inetIPUtils.findFirstNonLoopbackHostInfo().getIpAddress();
+ int index = ip.indexOf('%');
+ ip = index > 0 ? ip.substring(0, index) : ip;
+ ip = "["+ip+"]";
+ }else {
+ throw new IllegalArgumentException(
+ "please checking the type of IP " + ipType);
+ }
}
else {
NetworkInterface netInterface = NetworkInterface
@@ -258,6 +280,7 @@ public class NacosDiscoveryProperties {
while (inetAddress.hasMoreElements()) {
InetAddress currentAddress = inetAddress.nextElement();
if (currentAddress instanceof Inet4Address
+ || currentAddress instanceof Inet6Address
&& !currentAddress.isLoopbackAddress()) {
ip = currentAddress.getHostAddress();
break;
@@ -312,6 +335,10 @@ public class NacosDiscoveryProperties {
this.logName = logName;
}
+ public void setInetIPUtils(InetIPv6Utils inetIPUtils){
+ this.inetIPUtils = inetIPUtils;
+ }
+
public void setInetUtils(InetUtils inetUtils) {
this.inetUtils = inetUtils;
}
@@ -372,6 +399,14 @@ public class NacosDiscoveryProperties {
this.port = port;
}
+ public String getIpType() {
+ return ipType;
+ }
+
+ public void setIpType(String ipType) {
+ this.ipType = ipType;
+ }
+
public boolean isSecure() {
return secure;
}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/InetIPv6Utils.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/InetIPv6Utils.java
new file mode 100644
index 000000000..3a596d7e2
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/InetIPv6Utils.java
@@ -0,0 +1,158 @@
+package com.alibaba.cloud.nacos.intetuntil;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.cloud.commons.util.InetUtils;
+import org.springframework.cloud.commons.util.InetUtilsProperties;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author HH
+ */
+public class InetIPv6Utils implements Closeable {
+ private final ExecutorService executorService;
+
+ private final Log log = LogFactory.getLog(InetIPv6Utils.class);
+
+ private final InetUtilsProperties properties;
+
+ public InetIPv6Utils(final InetUtilsProperties properties) {
+ this.properties = properties;
+ this.executorService = Executors.newSingleThreadExecutor((r) -> {
+ Thread thread = new Thread(r);
+ thread.setName("spring.cloud.alibaba.inetutilsIPV6");
+ thread.setDaemon(true);
+ return thread;
+ });
+ }
+
+ public void close() {
+ this.executorService.shutdown();
+ }
+
+ public InetUtils.HostInfo findFirstNonLoopbackHostInfo() {
+ InetAddress address = this.findFirstNonLoopbackIPv6Address();
+ if (address != null) {
+ return this.convertAddress(address);
+ } else {
+ InetUtils.HostInfo hostInfo = new InetUtils.HostInfo();
+ this.properties.setDefaultIpAddress("0:0:0:0:0:0:0:1");
+ hostInfo.setHostname(this.properties.getDefaultHostname());
+ hostInfo.setIpAddress(this.properties.getDefaultIpAddress());
+ return hostInfo;
+ }
+ }
+
+ public InetAddress findFirstNonLoopbackIPv6Address() {
+ InetAddress address = null;
+
+ try {
+ int lowest = Integer.MAX_VALUE;
+ for (Enumeration nics = NetworkInterface.getNetworkInterfaces();
+ nics.hasMoreElements();) {
+ NetworkInterface ifc = nics.nextElement();
+ if (ifc.isUp()) {
+ log.trace("Testing interface:" + ifc.getDisplayName());
+ if (ifc.getIndex() < lowest || address == null) {
+ lowest = ifc.getIndex();
+ }
+ else if (address != null) {
+ continue;
+ }
+
+ if (!ignoreInterface(ifc.getDisplayName())) {
+ for (Enumeration addrs = ifc
+ .getInetAddresses(); addrs.hasMoreElements();) {
+ InetAddress inetAddress = addrs.nextElement();
+ if (inetAddress instanceof Inet6Address
+ && !inetAddress.isLoopbackAddress()
+ && isPreferredAddress(inetAddress)) {
+ log.trace("Found non-loopback interface: "
+ + ifc.getDisplayName());
+ address = inetAddress;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (IOException e) {
+ log.error("Cannot get first non-loopback address", e);
+ }
+
+ if (address != null) {
+ return address;
+ }
+
+ try {
+ return InetAddress.getLocalHost();
+ }
+ catch (UnknownHostException e) {
+ log.warn("Unable to retrieve localhost");
+ }
+
+ return null;
+ }
+
+ boolean isPreferredAddress(InetAddress address) {
+ if (this.properties.isUseOnlySiteLocalInterfaces()) {
+ final boolean siteLocalAddress = address.isSiteLocalAddress();
+ if (!siteLocalAddress) {
+ log.trace("Ignoring address"+address.getHostAddress());
+ }
+ return siteLocalAddress;
+ }
+ final List preferredNetworks = this.properties.getPreferredNetworks();
+ if (preferredNetworks.isEmpty()) {
+ return true;
+ }
+ for (String regex : preferredNetworks) {
+ final String hostAddress = address.getHostAddress();
+ if (hostAddress.matches(regex) || hostAddress.startsWith(regex)) {
+ return true;
+ }
+ }
+ log.trace("Ignoring address: " + address.getHostAddress());
+ return false;
+ }
+
+ boolean ignoreInterface(String interfaceName) {
+ for (String regex : this.properties.getIgnoredInterfaces()) {
+ if (interfaceName.matches(regex)) {
+ log.trace("Ignoring interface: " + interfaceName);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public InetUtils.HostInfo convertAddress(final InetAddress address) {
+ InetUtils.HostInfo hostInfo = new InetUtils.HostInfo();
+ Future result = this.executorService.submit(address::getHostName);
+
+ String hostname;
+ try {
+ hostname = result.get(this.properties.getTimeoutSeconds(), TimeUnit.SECONDS);
+ }
+ catch (Exception e) {
+ log.info("Cannot determine local hostname");
+ hostname = "localhost";
+ }
+ hostInfo.setHostname(hostname);
+ hostInfo.setIpAddress(address.getHostAddress());
+ return hostInfo;
+ }
+}
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/UtilIPv6AutoConfiguration.java b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/UtilIPv6AutoConfiguration.java
new file mode 100644
index 000000000..f7588ec9e
--- /dev/null
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/java/com/alibaba/cloud/nacos/intetuntil/UtilIPv6AutoConfiguration.java
@@ -0,0 +1,28 @@
+package com.alibaba.cloud.nacos.intetuntil;
+
+import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
+import org.springframework.cloud.commons.util.InetUtilsProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+/**
+ * @author HH
+ */
+@Configuration(proxyBeanMethods = false)
+@ConditionalOnDiscoveryEnabled
+@ConditionalOnNacosDiscoveryEnabled
+public class UtilIPv6AutoConfiguration {
+ public UtilIPv6AutoConfiguration() {
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public InetIPv6Utils inetUtils(InetUtilsProperties properties) {
+ return new InetIPv6Utils(properties);
+ }
+}
+
diff --git a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories
index dad08529a..92f91f592 100644
--- a/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-discovery/src/main/resources/META-INF/spring.factories
@@ -6,7 +6,8 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.discovery.NacosDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.reactive.NacosReactiveDiscoveryClientConfiguration,\
com.alibaba.cloud.nacos.discovery.configclient.NacosConfigServerAutoConfiguration,\
- com.alibaba.cloud.nacos.NacosServiceAutoConfiguration
+ com.alibaba.cloud.nacos.NacosServiceAutoConfiguration,\
+ com.alibaba.cloud.nacos.intetuntil.InetIPv6Utils
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.discovery.configclient.NacosDiscoveryClientConfigServiceBootstrapConfiguration
org.springframework.context.ApplicationListener=\