Skip to content

feat:support ipv6. #610

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.api.utils.CollectionUtils;
import com.tencent.polaris.api.utils.IPAddressUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.client.flow.BaseFlow;
import com.tencent.polaris.client.pojo.Node;
Expand Down Expand Up @@ -76,7 +77,7 @@ public ServiceAddressRepository(List<String> addresses, String clientId, Extensi
if (StringUtils.isNotBlank(address)) {
int colonIdx = address.lastIndexOf(":");
if (colonIdx > 0 && colonIdx < address.length() - 1) {
String host = address.substring(0, colonIdx);
String host = IPAddressUtils.getIpCompatible(address.substring(0, colonIdx));
try {
int port = Integer.parseInt(address.substring(colonIdx + 1));
nodes.add(new Node(host, port));
Expand Down Expand Up @@ -128,10 +129,11 @@ public Node getServiceAddressNode() throws PolarisException {
return node;
}
Instance instance = getDiscoverInstance();
String host = IPAddressUtils.getIpCompatible(instance.getHost());
if (LOG.isDebugEnabled()) {
LOG.debug("success to get instance for service {}, instance is {}:{}", remoteCluster, instance.getHost(), instance.getPort());
LOG.debug("success to get instance for service {}, instance is {}:{}", remoteCluster, host, instance.getPort());
}
return new Node(instance.getHost(), instance.getPort());
return new Node(IPAddressUtils.getIpCompatible(host), instance.getPort());
}

private Instance getDiscoverInstance() throws PolarisException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,14 @@ public class MetadataConstants {
* local host port.
*/
public static final String LOCAL_PORT = "LOCAL_PORT";

/**
* IPV4.
*/
public static String ADDRESS_IPV4 = "ADDRESS_IPV4";

/**
* IPV6.
*/
public static String ADDRESS_IPV6 = "ADDRESS_IPV6";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Tencent is pleased to support the open source community by making polaris-java available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 com.tencent.polaris.api.pojo;

import com.tencent.polaris.api.utils.MapUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.metadata.core.constant.MetadataConstants;

import java.util.Collection;
import java.util.Map;

/**
* Wrap for Instance.
*
* @author Haotian Zhang
*/
public class InstanceWrap implements Instance {

private final Instance originalInstance;

private final String host;

public InstanceWrap(Instance originalInstance, boolean isPreferIpv6) {
this.originalInstance = originalInstance;
String host = "";
if (isPreferIpv6 && MapUtils.isNotEmpty(originalInstance.getMetadata())) {
host = originalInstance.getMetadata().get(MetadataConstants.ADDRESS_IPV6);
} else if (MapUtils.isNotEmpty(originalInstance.getMetadata())) {
host = originalInstance.getMetadata().get(MetadataConstants.ADDRESS_IPV4);
}
if (StringUtils.isBlank(host)) {
host = originalInstance.getHost();
}
this.host = host;
}

@Override
public String getRevision() {
return originalInstance.getRevision();
}

@Override
public CircuitBreakerStatus getCircuitBreakerStatus() {
return originalInstance.getCircuitBreakerStatus();
}

@Override
public Collection<StatusDimension> getStatusDimensions() {
return originalInstance.getStatusDimensions();
}

@Override
public CircuitBreakerStatus getCircuitBreakerStatus(StatusDimension statusDimension) {
return originalInstance.getCircuitBreakerStatus(statusDimension);
}

@Override
public boolean isHealthy() {
return originalInstance.isHealthy();
}

@Override
public boolean isIsolated() {
return originalInstance.isIsolated();
}

@Override
public String getProtocol() {
return originalInstance.getProtocol();
}

@Override
public String getId() {
return originalInstance.getId();
}

@Override
public String getVersion() {
return originalInstance.getVersion();
}

@Override
public Map<String, String> getMetadata() {
return originalInstance.getMetadata();
}

@Override
public boolean isEnableHealthCheck() {
return originalInstance.isEnableHealthCheck();
}

@Override
public String getRegion() {
return originalInstance.getRegion();
}

@Override
public String getZone() {
return originalInstance.getZone();
}

@Override
public String getCampus() {
return originalInstance.getCampus();
}

@Override
public int getPriority() {
return originalInstance.getPriority();
}

@Override
public int getWeight() {
return originalInstance.getWeight();
}

@Override
public String getLogicSet() {
return originalInstance.getLogicSet();
}

@Override
public Long getCreateTime() {
return originalInstance.getCreateTime();
}

@Override
public String getNamespace() {
return originalInstance.getNamespace();
}

@Override
public String getService() {
return originalInstance.getService();
}

@Override
public String getHost() {
return host;
}

@Override
public int getPort() {
return originalInstance.getPort();
}

@Override
public int compareTo(Instance o) {
return originalInstance.compareTo(o);
}

@Override
public String toString() {
return "InstanceWrap{" +
"originalInstance=" + originalInstance +
", host='" + host + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
import com.tencent.polaris.logging.LoggerFactory;
import org.slf4j.Logger;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* @author Haotian Zhang
Expand Down Expand Up @@ -54,4 +56,21 @@ public static String getHostName() {
return "";
}
}

/**
* 检查主机地址是否为IPv6格式
*
* @param host
* @return
*/
public static boolean checkIpv6Host(String host) {
try {
if (StringUtils.isNotBlank(host)) {
return InetAddress.getByName(host) instanceof Inet6Address;
}
} catch (UnknownHostException e) {
// ignore
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* Tencent is pleased to support the open source community by making polaris-java available.
*
* Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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 com.tencent.polaris.api.pojo;

import com.tencent.polaris.metadata.core.constant.MetadataConstants;
import org.junit.Test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;

public class InstanceWrapTest {

@Test
public void testConstructorWithIpv6Preference() {
// Mock data
DefaultInstance originalInstance = new DefaultInstance();
Map<String, String> metadata = new HashMap<>();
metadata.put(MetadataConstants.ADDRESS_IPV6, "::1");
originalInstance.setMetadata(metadata);
originalInstance.setHost("127.0.0.1");

// Test with IPv6 preference
InstanceWrap instanceWrap = new InstanceWrap(originalInstance, true);

// Verify host is set to IPv6 address
assertThat(instanceWrap.getHost()).isEqualTo("::1");
}

@Test
public void testConstructorWithIpv4Preference() {
// Mock data
DefaultInstance originalInstance = new DefaultInstance();
Map<String, String> metadata = new HashMap<>();
metadata.put(MetadataConstants.ADDRESS_IPV4, "192.168.1.1");
originalInstance.setMetadata(metadata);
originalInstance.setHost("::1");

// Test with IPv4 preference
InstanceWrap instanceWrap = new InstanceWrap(originalInstance, false);

// Verify host is set to IPv4 address
assertThat(instanceWrap.getHost()).isEqualTo("192.168.1.1");
}

@Test
public void testConstructorWithNoMetadata() {
// Mock data
DefaultInstance originalInstance = new DefaultInstance();
originalInstance.setHost("127.0.0.1");
originalInstance.setMetadata(Collections.emptyMap());

// Test with no metadata
InstanceWrap instanceWrap = new InstanceWrap(originalInstance, true);

// Verify host is set to original host
assertThat(instanceWrap.getHost()).isEqualTo("127.0.0.1");
}

@Test
public void testConstructorWithBlankMetadata() {
// Mock data
DefaultInstance originalInstance = new DefaultInstance();
originalInstance.setHost("127.0.0.1");
Map<String, String> metadata = new HashMap<>();
metadata.put(MetadataConstants.ADDRESS_IPV6, "");
originalInstance.setMetadata(metadata);

// Test with blank metadata
InstanceWrap instanceWrap = new InstanceWrap(originalInstance, true);

// Verify host is set to original host
assertThat(instanceWrap.getHost()).isEqualTo("127.0.0.1");
}
}
Loading