From 5d6f7777283eae8523ad66512fefd9c237a029db Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Mon, 23 Dec 2024 09:21:00 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E9=9B=86=E7=BE=A4=E5=A4=96=E8=AE=BF?= =?UTF-8?q?=E9=97=AE=E4=BB=A3=E7=A0=81=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../seata/common/ConfigurationKeys.java | 11 ++ .../exception/ParseEndpointException.java | 22 ++++ .../apache/seata/common/metadata/Node.java | 86 +++++++++++++ .../org/apache/seata/common/util/NetUtil.java | 3 + .../raft/RaftRegistryServiceImpl.java | 113 ++++++++++++++++-- .../SeataCoreEnvironmentPostProcessor.java | 3 + .../boot/autoconfigure/StarterConstants.java | 2 + .../registry/RegistryMetadataProperties.java | 20 ++++ .../server/cluster/raft/RaftStateMachine.java | 4 +- .../sync/msg/dto/RaftClusterMetadata.java | 9 +- 10 files changed, 259 insertions(+), 14 deletions(-) create mode 100644 common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java create mode 100644 seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java diff --git a/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java b/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java index 840e0298004..3bb4c9873ff 100644 --- a/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java +++ b/common/src/main/java/org/apache/seata/common/ConfigurationKeys.java @@ -1110,4 +1110,15 @@ public interface ConfigurationKeys { * The constant META_PREFIX */ String META_PREFIX = SEATA_FILE_ROOT_CONFIG + FILE_CONFIG_SPLIT_CHAR + FILE_ROOT_REGISTRY + FILE_CONFIG_SPLIT_CHAR + "metadata."; + + /** + * The constant SERVER_REGISTRY_METADATA_PREFIX + */ + String SERVER_REGISTRY_METADATA_PREFIX = SERVER_PREFIX + FILE_ROOT_REGISTRY + ".metadata"; + + /** + * The constant SERVER_REGISTRY_METADATA_EXTERNAL + */ + String SERVER_REGISTRY_METADATA_EXTERNAL = SERVER_REGISTRY_METADATA_PREFIX + ".external"; + } diff --git a/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java b/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java new file mode 100644 index 00000000000..c78a677f94b --- /dev/null +++ b/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java @@ -0,0 +1,22 @@ +package org.apache.seata.common.exception; + +public class ParseEndpointException extends RuntimeException { + public ParseEndpointException() { + } + + public ParseEndpointException(String message) { + super(message); + } + + public ParseEndpointException(String message, Throwable cause) { + super(message, cause); + } + + public ParseEndpointException(Throwable cause) { + super(cause); + } + + public ParseEndpointException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/common/src/main/java/org/apache/seata/common/metadata/Node.java b/common/src/main/java/org/apache/seata/common/metadata/Node.java index 92d43c366f8..f2ed93cf4ec 100644 --- a/common/src/main/java/org/apache/seata/common/metadata/Node.java +++ b/common/src/main/java/org/apache/seata/common/metadata/Node.java @@ -18,10 +18,13 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.seata.common.exception.ParseEndpointException; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.List; +import java.util.ArrayList; public class Node { @@ -195,4 +198,87 @@ public String toString() { } } + private Node.ExternalEndpoint createExternalEndpoint(String host, int controllerPort, int transactionPort) { + return new Node.ExternalEndpoint(host, controllerPort, transactionPort); + } + + public List createExternalEndpoints(String external) { + List externalEndpoints = new ArrayList<>(); + String[] split = external.split(","); + + for (String s : split) { + String[] item = s.split(":"); + if (item.length == 4) { + try { + String seataHostName = item[0]; + String host = item[1]; + int controllerPort = Integer.parseInt(item[2]); + int transactionPort = Integer.parseInt(item[3]); + if (!seataHostName.equals(System.getenv("SEATA_HOST_NAME"))) { + continue; + } + externalEndpoints.add(createExternalEndpoint(host, controllerPort, transactionPort)); + } catch (NumberFormatException e) { + throw new ParseEndpointException("Invalid port number in: " + s); + } + } else { + throw new ParseEndpointException("Invalid format for endpoint: " + s); + } + } + return externalEndpoints; + } + + public void updateMetadataWithExternalEndpoints(Map metadata, List externalEndpoints) { + Object obj = metadata.get("external"); + if (obj == null) { + if (!externalEndpoints.isEmpty()) { + metadata.put("external", externalEndpoints); + return; + } + return; + } + if (obj instanceof List) { + List oldList = (List) obj; + oldList.addAll(externalEndpoints); + } else { + throw new ParseEndpointException("Metadata 'external' is not a List."); + } + } + + public static class ExternalEndpoint { + + private String host; + private int controlPort; + private int transactionPort; + + public ExternalEndpoint(String host, int controlPort, int transactionPort) { + this.host = host; + this.controlPort = controlPort; + this.transactionPort = transactionPort; + } + + public String getHost() { + return host; + } + + public void setHost(String host) { + this.host = host; + } + + public int getControlPort() { + return controlPort; + } + + public void setControlPort(int controlPort) { + this.controlPort = controlPort; + } + + public int getTransactionPort() { + return transactionPort; + } + + public void setTransactionPort(int transactionPort) { + this.transactionPort = transactionPort; + } + } } diff --git a/common/src/main/java/org/apache/seata/common/util/NetUtil.java b/common/src/main/java/org/apache/seata/common/util/NetUtil.java index 008f0839bef..fa3df4f2994 100644 --- a/common/src/main/java/org/apache/seata/common/util/NetUtil.java +++ b/common/src/main/java/org/apache/seata/common/util/NetUtil.java @@ -90,6 +90,9 @@ public static String toIpAddress(SocketAddress address) { * @return the string */ public static String toStringAddress(InetSocketAddress address) { + if (address.getAddress() == null) { + return address.getHostString() + ":" + address.getPort(); + } return address.getAddress().getHostAddress() + ":" + address.getPort(); } diff --git a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java index 8ba0d2256ed..1a7365d9335 100644 --- a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java +++ b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java @@ -24,6 +24,9 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.LinkedHashMap; +import java.util.Optional; +import java.util.Arrays; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadLocalRandom; @@ -38,6 +41,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.seata.common.ConfigurationKeys; import org.apache.seata.common.exception.AuthenticationFailedException; +import org.apache.seata.common.exception.ParseEndpointException; import org.apache.seata.common.exception.RetryableException; import org.apache.seata.common.metadata.Metadata; import org.apache.seata.common.metadata.MetadataResponse; @@ -45,6 +49,7 @@ import org.apache.seata.common.thread.NamedThreadFactory; import org.apache.seata.common.util.CollectionUtils; import org.apache.seata.common.util.HttpClientUtil; +import org.apache.seata.common.util.NetUtil; import org.apache.seata.common.util.StringUtils; import org.apache.seata.config.ConfigChangeListener; import org.apache.seata.config.Configuration; @@ -114,10 +119,13 @@ public class RaftRegistryServiceImpl implements RegistryService> ALIVE_NODES = new ConcurrentHashMap<>(); + private static final String PREFERRED_NETWORKS; + static { TOKEN_EXPIRE_TIME_IN_MILLISECONDS = CONFIG.getLong(getTokenExpireTimeInMillisecondsKey(), 29 * 60 * 1000L); USERNAME = CONFIG.getConfig(getRaftUserNameKey()); PASSWORD = CONFIG.getConfig(getRaftPassWordKey()); + PREFERRED_NETWORKS = CONFIG.getConfig(getPreferredNetworks()); } private RaftRegistryServiceImpl() { @@ -221,7 +229,7 @@ private static String queryHttpAddress(String clusterName, String group) { List inetSocketAddresses = ALIVE_NODES.get(CURRENT_TRANSACTION_SERVICE_GROUP); if (CollectionUtils.isEmpty(inetSocketAddresses)) { addressList = - nodeList.stream().map(node -> node.getControl().createAddress()).collect(Collectors.toList()); + nodeList.stream().map(RaftRegistryServiceImpl::selectControlEndpointStr).collect(Collectors.toList()); } else { stream = inetSocketAddresses.stream(); } @@ -234,15 +242,20 @@ private static String queryHttpAddress(String clusterName, String group) { Map map = new HashMap<>(); if (CollectionUtils.isNotEmpty(nodeList)) { for (Node node : nodeList) { - map.put(new InetSocketAddress(node.getTransaction().getHost(), node.getTransaction().getPort()).getAddress().getHostAddress() - + IP_PORT_SPLIT_CHAR + node.getTransaction().getPort(), node); + InetSocketAddress inetSocketAddress = selectTransactionEndpoint(node); + map.put(inetSocketAddress.getHostString() + + IP_PORT_SPLIT_CHAR + inetSocketAddress.getPort(), node); } } addressList = stream.map(inetSocketAddress -> { - String host = inetSocketAddress.getAddress().getHostAddress(); + String host = NetUtil.toStringAddress(inetSocketAddress); Node node = map.get(host + IP_PORT_SPLIT_CHAR + inetSocketAddress.getPort()); + InetSocketAddress controlEndpoint = null; + if (node != null) { + controlEndpoint = selectControlEndpoint(node); + } return host + IP_PORT_SPLIT_CHAR - + (node != null ? node.getControl().getPort() : inetSocketAddress.getPort()); + + (controlEndpoint != null ? controlEndpoint.getPort() : inetSocketAddress.getPort()); }).collect(Collectors.toList()); return addressList.get(ThreadLocalRandom.current().nextInt(addressList.size())); } @@ -263,6 +276,11 @@ private static String getRaftPassWordKey() { REGISTRY_TYPE, PRO_PASSWORD_KEY); } + private static String getPreferredNetworks() { + return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, + "preferredNetworks"); + } + private static String getTokenExpireTimeInMillisecondsKey() { return String.join(ConfigurationKeys.FILE_CONFIG_SPLIT_CHAR, ConfigurationKeys.FILE_ROOT_REGISTRY, REGISTRY_TYPE, TOKEN_VALID_TIME_MS_KEY); @@ -276,9 +294,82 @@ private static boolean isTokenExpired() { return System.currentTimeMillis() >= tokenExpiredTime; } - private InetSocketAddress convertInetSocketAddress(Node node) { - Node.Endpoint endpoint = node.getTransaction(); - return new InetSocketAddress(endpoint.getHost(), endpoint.getPort()); + private static String selectControlEndpointStr(Node node) { + InetSocketAddress control = selectControlEndpoint(node); + return NetUtil.toStringAddress(control); + } + + private static String selectTransactionEndpointStr(Node node) { + InetSocketAddress transaction = selectTransactionEndpoint( node); + return NetUtil.toStringAddress(transaction); + } + + private static InetSocketAddress selectControlEndpoint(Node node) { + return selectEndpoint("control", node); + } + + private static InetSocketAddress selectTransactionEndpoint(Node node) { + return selectEndpoint("transaction", node); + } + + private static InetSocketAddress selectEndpoint(String type, Node node) { + if (StringUtils.isBlank(PREFERRED_NETWORKS)) { + // 采取默认的方式,直接使用node.control node.transaction + switch (type) { + case "control": + return new InetSocketAddress(node.getControl().getHost(), node.getControl().getPort()); + case "transaction": + return new InetSocketAddress(node.getTransaction().getHost(), node.getTransaction().getPort()); + } + } + Node.ExternalEndpoint externalEndpoint = selectExternalEndpoint(node, PREFERRED_NETWORKS.split(";")); + switch (type) { + case "control": + return new InetSocketAddress(externalEndpoint.getHost(), externalEndpoint.getControlPort()); + case "transaction": + return new InetSocketAddress(externalEndpoint.getHost(), externalEndpoint.getTransactionPort()); + } + throw new ParseEndpointException("Select endpoint is fail."); + } + + private static Node.ExternalEndpoint selectExternalEndpoint(Node node, String[] preferredNetworks) { + Map metadata = node.getMetadata(); + if (CollectionUtils.isEmpty(metadata)) { + throw new ParseEndpointException("Node metadata is empty."); + } + + Object external = metadata.get("external"); + + if (external instanceof List) { + List> externalEndpoints = (List>) external; + + if (CollectionUtils.isEmpty(externalEndpoints)) { + throw new ParseEndpointException("ExternalEndpoints should not be empty."); + } + + for (LinkedHashMap externalEndpoint : externalEndpoints) { + String ip = Optional.ofNullable(externalEndpoint.get("host")) + .map(Object::toString) + .orElse(""); + + if (isPreferredNetwork(ip, Arrays.asList(preferredNetworks))) { + return createExternalEndpoint(externalEndpoint, ip); + } + } + } + throw new ParseEndpointException("No ExternalEndpoints value matches."); + } + + private static boolean isPreferredNetwork(String ip, List preferredNetworks) { + return preferredNetworks.stream().anyMatch(regex -> + StringUtils.isNotBlank(regex) && (ip.matches(regex) || ip.startsWith(regex)) + ); + } + + private static Node.ExternalEndpoint createExternalEndpoint(LinkedHashMap externalEndpoint, String ip) { + int controlPort = Integer.parseInt(externalEndpoint.get("controlPort").toString()); + int transactionPort = Integer.parseInt(externalEndpoint.get("transactionPort").toString()); + return new Node.ExternalEndpoint(ip, controlPort, transactionPort); } @Override @@ -292,7 +383,7 @@ public List aliveLookup(String transactionServiceGroup) { String clusterName = getServiceGroup(transactionServiceGroup); Node leader = METADATA.getLeader(clusterName); if (leader != null) { - return Collections.singletonList(convertInetSocketAddress(leader)); + return Collections.singletonList(selectTransactionEndpoint(leader)); } } return RegistryService.super.aliveLookup(transactionServiceGroup); @@ -340,7 +431,7 @@ public List refreshAliveLookup(String transactionServiceGroup List aliveAddress) { if (METADATA.isRaftMode()) { Node leader = METADATA.getLeader(getServiceGroup(transactionServiceGroup)); - InetSocketAddress leaderAddress = convertInetSocketAddress(leader); + InetSocketAddress leaderAddress = selectTransactionEndpoint(leader); return ALIVE_NODES.put(transactionServiceGroup, aliveAddress.isEmpty() ? aliveAddress : aliveAddress.parallelStream().filter(inetSocketAddress -> { // Since only follower will turn into leader, only the follower node needs to be listened to @@ -478,7 +569,7 @@ public List lookup(String key) throws Exception { } List nodes = METADATA.getNodes(clusterName); if (CollectionUtils.isNotEmpty(nodes)) { - return nodes.parallelStream().map(this::convertInetSocketAddress).collect(Collectors.toList()); + return nodes.parallelStream().map(RaftRegistryServiceImpl::selectTransactionEndpoint).collect(Collectors.toList()); } return Collections.emptyList(); } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java index 67bc7bd75ab..bfa4923469f 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataCoreEnvironmentPostProcessor.java @@ -40,6 +40,7 @@ import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryRedisProperties; import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistrySofaProperties; import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryZooKeeperProperties; +import org.apache.seata.spring.boot.autoconfigure.properties.registry.RegistryMetadataProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; import org.springframework.core.Ordered; @@ -69,6 +70,7 @@ import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.SHUTDOWN_PREFIX; import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.THREAD_FACTORY_PREFIX; import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.TRANSPORT_PREFIX; +import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.REGISTRY_METADATA_PREFIX; public class SeataCoreEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { @@ -90,6 +92,7 @@ public static void init() { PROPERTY_BEAN_MAP.put(CONFIG_PREFIX, ConfigProperties.class); PROPERTY_BEAN_MAP.put(CONFIG_FILE_PREFIX, ConfigFileProperties.class); PROPERTY_BEAN_MAP.put(REGISTRY_PREFIX, RegistryProperties.class); + PROPERTY_BEAN_MAP.put(REGISTRY_METADATA_PREFIX, RegistryMetadataProperties.class); PROPERTY_BEAN_MAP.put(CONFIG_NACOS_PREFIX, ConfigNacosProperties.class); PROPERTY_BEAN_MAP.put(CONFIG_CONSUL_PREFIX, ConfigConsulProperties.class); diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java index 5ec088d43ff..db09911af18 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java @@ -58,6 +58,8 @@ public interface StarterConstants { String REGISTRY_SOFA_PREFIX = REGISTRY_PREFIX + ".sofa"; String REGISTRY_CUSTOM_PREFIX = REGISTRY_PREFIX + ".custom"; + String REGISTRY_METADATA_PREFIX = REGISTRY_PREFIX + ".metadata"; + String CONFIG_PREFIX = SEATA_PREFIX + ".config"; String CONFIG_NACOS_PREFIX = CONFIG_PREFIX + ".nacos"; String CONFIG_CONSUL_PREFIX = CONFIG_PREFIX + ".consul"; diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java new file mode 100644 index 00000000000..5ad55f2a9ca --- /dev/null +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java @@ -0,0 +1,20 @@ +package org.apache.seata.spring.boot.autoconfigure.properties.registry; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import static org.apache.seata.spring.boot.autoconfigure.StarterConstants.REGISTRY_METADATA_PREFIX; + +@Component +@ConfigurationProperties(prefix = REGISTRY_METADATA_PREFIX) +public class RegistryMetadataProperties { + private String external; + + public String getExternal() { + return external; + } + + public RegistryMetadataProperties setExternal(String external) { + this.external = external; + return this; + } +} diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java b/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java index 9b49ba011ff..a1069232efe 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java @@ -366,7 +366,7 @@ public RaftClusterMetadata changeOrInitRaftClusterMetadata() { Integer.parseInt( ((Environment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT)) .getProperty("server.port", String.valueOf(7091))), - group, Collections.emptyMap()); + group, new HashMap<>()); leader.setRole(ClusterRole.LEADER); raftClusterMetadata.setLeader(leader); } @@ -406,7 +406,7 @@ private void syncCurrentNodeInfo(PeerId leaderPeerId) { Integer.parseInt( ((Environment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT)) .getProperty("server.port", String.valueOf(7091))), - group, Collections.emptyMap()); + group, new HashMap<>()); InvokeContext invokeContext = new InvokeContext(); PutNodeMetadataRequest putNodeInfoRequest = new PutNodeMetadataRequest(node); Configuration configuration = RouteTable.getInstance().getConfiguration(group); diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java index 2e3e217a96c..357efa5f6a2 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java @@ -21,10 +21,11 @@ import java.util.List; import java.util.Map; import java.util.Optional; - import org.apache.seata.common.metadata.Node; import org.apache.seata.common.util.StringUtils; +import org.apache.seata.config.ConfigurationFactory; import org.apache.seata.core.protocol.Version; +import static org.apache.seata.common.ConfigurationKeys.SERVER_REGISTRY_METADATA_EXTERNAL; /** */ @@ -41,6 +42,8 @@ public class RaftClusterMetadata implements Serializable { private long term; public RaftClusterMetadata() { + System.setProperty("SERVER_REGISTRY_METADATA_EXTERNAL_VALUE", ConfigurationFactory.getInstance() + .getConfig(SERVER_REGISTRY_METADATA_EXTERNAL)); } public RaftClusterMetadata(long term) { @@ -55,6 +58,10 @@ public Node createNode(String host, int txPort, int internalPort, int controlPor node.setGroup(group); node.setVersion(Version.getCurrent()); node.setInternal(node.createEndpoint(host, internalPort, "raft")); + String serverRegistryMetadataExternalValue = System.getProperty("SERVER_REGISTRY_METADATA_EXTERNAL_VALUE"); + if (metadata != null && StringUtils.isNotEmpty(serverRegistryMetadataExternalValue)) { + node.updateMetadataWithExternalEndpoints(metadata, node.createExternalEndpoints(serverRegistryMetadataExternalValue)); + } Optional.ofNullable(metadata).ifPresent(node::setMetadata); return node; } From 96ac1eea3d6d922e94812177a0715875611947ee Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sat, 28 Dec 2024 14:15:20 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/ParseEndpointException.java | 16 +++++++++ .../org/apache/seata/common/util/NetUtil.java | 13 +++++++ .../raft/RaftRegistryServiceImpl.java | 2 +- .../raft/RaftRegistryServiceImplTest.java | 34 +++++++++++++++++-- .../registry/RegistryMetadataProperties.java | 16 +++++++++ .../sync/msg/dto/RaftClusterMetadata.java | 10 +++--- 6 files changed, 83 insertions(+), 8 deletions(-) diff --git a/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java b/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java index c78a677f94b..e4f550d5480 100644 --- a/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java +++ b/common/src/main/java/org/apache/seata/common/exception/ParseEndpointException.java @@ -1,3 +1,19 @@ +/* + * 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.seata.common.exception; public class ParseEndpointException extends RuntimeException { diff --git a/common/src/main/java/org/apache/seata/common/util/NetUtil.java b/common/src/main/java/org/apache/seata/common/util/NetUtil.java index fa3df4f2994..2043f85c79a 100644 --- a/common/src/main/java/org/apache/seata/common/util/NetUtil.java +++ b/common/src/main/java/org/apache/seata/common/util/NetUtil.java @@ -96,6 +96,19 @@ public static String toStringAddress(InetSocketAddress address) { return address.getAddress().getHostAddress() + ":" + address.getPort(); } + /** + * To string host string. + * + * @param address the address + * @return the string + */ + public static String toStringHost(InetSocketAddress address) { + if (address.getAddress() == null) { + return address.getHostString(); + } + return address.getAddress().getHostAddress(); + } + /** * To inet socket address inet socket address. * diff --git a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java index 1a7365d9335..a835143e4ed 100644 --- a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java +++ b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java @@ -248,7 +248,7 @@ private static String queryHttpAddress(String clusterName, String group) { } } addressList = stream.map(inetSocketAddress -> { - String host = NetUtil.toStringAddress(inetSocketAddress); + String host = NetUtil.toStringHost(inetSocketAddress); Node node = map.get(host + IP_PORT_SPLIT_CHAR + inetSocketAddress.getPort()); InetSocketAddress controlEndpoint = null; if (node != null) { diff --git a/discovery/seata-discovery-raft/src/test/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImplTest.java b/discovery/seata-discovery-raft/src/test/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImplTest.java index e6c88fcc5c0..45b675dbe56 100644 --- a/discovery/seata-discovery-raft/src/test/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImplTest.java +++ b/discovery/seata-discovery-raft/src/test/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImplTest.java @@ -17,13 +17,18 @@ package org.apache.seata.discovery.registry.raft; -import org.apache.seata.common.util.HttpClientUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.seata.common.metadata.MetadataResponse; +import org.apache.seata.common.metadata.Node; +import org.apache.seata.common.util.*; import org.apache.seata.config.ConfigurationFactory; import org.apache.http.HttpStatus; import org.apache.http.StatusLine; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.entity.StringEntity; import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; @@ -33,7 +38,7 @@ import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.util.Map; +import java.util.*; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -53,6 +58,7 @@ public static void beforeClass() { System.setProperty("registry.raft.password", "seata"); System.setProperty("registry.raft.serverAddr", "127.0.0.1:8092"); System.setProperty("registry.raft.tokenValidityInMilliseconds", "10000"); + System.setProperty("registry.preferredNetworks", "10.10.*"); ConfigurationFactory.getInstance(); } @@ -145,4 +151,28 @@ public void testSecureTTL() throws NoSuchMethodException, InvocationTargetExcept assertEquals(true, rst); } + /** + * RaftRegistryServiceImpl#controlEndpointStr() + * RaftRegistryServiceImpl#transactionEndpointStr() + */ + @Test + public void testSelectEndpoint() throws JsonProcessingException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + String jsonString = "{\"nodes\":[{\"control\":{\"host\":\"v-0.svc-l.default.svc.cluster.local\",\"port\":7091},\"transaction\":{\"host\":\"v-0.svc-l.default.svc.cluster.local\",\"port\":8091},\"internal\":{\"host\":\"v-0.svc-l.default.svc.cluster.local\",\"port\":9091},\"group\":\"default\",\"role\":\"LEADER\",\"version\":\"2.3.0-SNAPSHOT\",\"metadata\":{\"external\":[{\"host\":\"192.168.105.7\",\"controlPort\":30071,\"transactionPort\":30091},{\"host\":\"10.10.105.7\",\"controlPort\":30071,\"transactionPort\":30091}]}},{\"control\":{\"host\":\"v-2.svc-l.default.svc.cluster.local\",\"port\":7091},\"transaction\":{\"host\":\"v-2.svc-l.default.svc.cluster.local\",\"port\":8091},\"internal\":{\"host\":\"v-2.svc-l.default.svc.cluster.local\",\"port\":9091},\"group\":\"default\",\"role\":\"FOLLOWER\",\"version\":\"2.3.0-SNAPSHOT\",\"metadata\":{\"external\":[{\"host\":\"192.168.105.7\",\"controlPort\":30073,\"transactionPort\":30093},{\"host\":\"10.10.105.7\",\"controlPort\":30073,\"transactionPort\":30093}]}},{\"control\":{\"host\":\"v-1.svc-l.default.svc.cluster.local\",\"port\":7091},\"transaction\":{\"host\":\"v-1.svc-l.default.svc.cluster.local\",\"port\":8091},\"internal\":{\"host\":\"v-1.svc-l.default.svc.cluster.local\",\"port\":9091},\"group\":\"default\",\"role\":\"FOLLOWER\",\"version\":\"2.3.0-SNAPSHOT\",\"metadata\":{\"external\":[{\"host\":\"192.168.105.7\",\"controlPort\":30072,\"transactionPort\":30092},{\"host\":\"10.10.105.7\",\"controlPort\":30072,\"transactionPort\":30092}]}}],\"storeMode\":\"raft\",\"term\":1}"; + + Method selectControlEndpointStrMethod = RaftRegistryServiceImpl.class.getDeclaredMethod("selectControlEndpointStr", Node.class); + selectControlEndpointStrMethod.setAccessible(true); + Method selectTransactionEndpointStrMethod = RaftRegistryServiceImpl.class.getDeclaredMethod("selectTransactionEndpointStr", Node.class); + selectTransactionEndpointStrMethod.setAccessible(true); + + ObjectMapper objectMapper = new ObjectMapper(); + MetadataResponse metadataResponse = objectMapper.readValue(jsonString, MetadataResponse.class); + List nodes = metadataResponse.getNodes(); + + for (Node node : nodes) { + String controlEndpointStr = (String) selectControlEndpointStrMethod.invoke(null, node);; + String transactionEndpointStr = (String) selectTransactionEndpointStrMethod.invoke(null, node);; + Assertions.assertTrue(controlEndpointStr.contains("10.10.105.7:3007")); + Assertions.assertTrue(transactionEndpointStr.contains("10.10.105.7:3009")); + } + } } diff --git a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java index 5ad55f2a9ca..595b322b79a 100644 --- a/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java +++ b/seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java @@ -1,3 +1,19 @@ +/* + * 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.seata.spring.boot.autoconfigure.properties.registry; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java index 357efa5f6a2..7c6d7031f8c 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java @@ -21,11 +21,12 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import org.apache.seata.common.holder.ObjectHolder; import org.apache.seata.common.metadata.Node; import org.apache.seata.common.util.StringUtils; -import org.apache.seata.config.ConfigurationFactory; import org.apache.seata.core.protocol.Version; -import static org.apache.seata.common.ConfigurationKeys.SERVER_REGISTRY_METADATA_EXTERNAL; +import org.springframework.core.env.ConfigurableEnvironment; +import static org.apache.seata.common.Constants.OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT; /** */ @@ -42,8 +43,6 @@ public class RaftClusterMetadata implements Serializable { private long term; public RaftClusterMetadata() { - System.setProperty("SERVER_REGISTRY_METADATA_EXTERNAL_VALUE", ConfigurationFactory.getInstance() - .getConfig(SERVER_REGISTRY_METADATA_EXTERNAL)); } public RaftClusterMetadata(long term) { @@ -58,7 +57,8 @@ public Node createNode(String host, int txPort, int internalPort, int controlPor node.setGroup(group); node.setVersion(Version.getCurrent()); node.setInternal(node.createEndpoint(host, internalPort, "raft")); - String serverRegistryMetadataExternalValue = System.getProperty("SERVER_REGISTRY_METADATA_EXTERNAL_VALUE"); + ConfigurableEnvironment environment= (ConfigurableEnvironment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); + String serverRegistryMetadataExternalValue = environment.resolvePlaceholders("${registry.metadata.external:${seata.registry.metadata.external:}}"); if (metadata != null && StringUtils.isNotEmpty(serverRegistryMetadataExternalValue)) { node.updateMetadataWithExternalEndpoints(metadata, node.createExternalEndpoints(serverRegistryMetadataExternalValue)); } From 42da1929ba1478ac60ddade8fe4ab91f279be460 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sat, 28 Dec 2024 14:20:43 +0800 Subject: [PATCH 03/10] update --- .../seata/discovery/registry/raft/RaftRegistryServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java index a835143e4ed..c43c3a04bec 100644 --- a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java +++ b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java @@ -314,7 +314,7 @@ private static InetSocketAddress selectTransactionEndpoint(Node node) { private static InetSocketAddress selectEndpoint(String type, Node node) { if (StringUtils.isBlank(PREFERRED_NETWORKS)) { - // 采取默认的方式,直接使用node.control node.transaction + // Use the default method, directly using node.control and node.transaction switch (type) { case "control": return new InetSocketAddress(node.getControl().getHost(), node.getControl().getPort()); From 90683ea48eec4b1215a1c46b41fca27d2069de12 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sat, 28 Dec 2024 15:23:07 +0800 Subject: [PATCH 04/10] update --- .../discovery/registry/raft/RaftRegistryServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java index c43c3a04bec..c7b9a8b3630 100644 --- a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java +++ b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java @@ -41,6 +41,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.seata.common.ConfigurationKeys; import org.apache.seata.common.exception.AuthenticationFailedException; +import org.apache.seata.common.exception.NotSupportYetException; import org.apache.seata.common.exception.ParseEndpointException; import org.apache.seata.common.exception.RetryableException; import org.apache.seata.common.metadata.Metadata; @@ -320,6 +321,8 @@ private static InetSocketAddress selectEndpoint(String type, Node node) { return new InetSocketAddress(node.getControl().getHost(), node.getControl().getPort()); case "transaction": return new InetSocketAddress(node.getTransaction().getHost(), node.getTransaction().getPort()); + default: + throw new NotSupportYetException("SelectEndpoint is not support type: " + type); } } Node.ExternalEndpoint externalEndpoint = selectExternalEndpoint(node, PREFERRED_NETWORKS.split(";")); @@ -328,8 +331,9 @@ private static InetSocketAddress selectEndpoint(String type, Node node) { return new InetSocketAddress(externalEndpoint.getHost(), externalEndpoint.getControlPort()); case "transaction": return new InetSocketAddress(externalEndpoint.getHost(), externalEndpoint.getTransactionPort()); + default: + throw new NotSupportYetException("SelectEndpoint is not support type: " + type); } - throw new ParseEndpointException("Select endpoint is fail."); } private static Node.ExternalEndpoint selectExternalEndpoint(Node node, String[] preferredNetworks) { From 82ca589701bcf9795c07b8e79e6b968f1035a21d Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sat, 28 Dec 2024 15:35:37 +0800 Subject: [PATCH 05/10] update --- .../discovery/registry/raft/RaftRegistryServiceImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java index c7b9a8b3630..06bed7b639d 100644 --- a/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java +++ b/discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java @@ -301,7 +301,7 @@ private static String selectControlEndpointStr(Node node) { } private static String selectTransactionEndpointStr(Node node) { - InetSocketAddress transaction = selectTransactionEndpoint( node); + InetSocketAddress transaction = selectTransactionEndpoint(node); return NetUtil.toStringAddress(transaction); } @@ -321,8 +321,8 @@ private static InetSocketAddress selectEndpoint(String type, Node node) { return new InetSocketAddress(node.getControl().getHost(), node.getControl().getPort()); case "transaction": return new InetSocketAddress(node.getTransaction().getHost(), node.getTransaction().getPort()); - default: - throw new NotSupportYetException("SelectEndpoint is not support type: " + type); + default: + throw new NotSupportYetException("SelectEndpoint is not support type: " + type); } } Node.ExternalEndpoint externalEndpoint = selectExternalEndpoint(node, PREFERRED_NETWORKS.split(";")); From 1d631e269591c7950545d151cea6f2d4dc436777 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sat, 28 Dec 2024 18:28:34 +0800 Subject: [PATCH 06/10] update --- .../server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java index 7c6d7031f8c..808ef4e8c43 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java @@ -57,7 +57,7 @@ public Node createNode(String host, int txPort, int internalPort, int controlPor node.setGroup(group); node.setVersion(Version.getCurrent()); node.setInternal(node.createEndpoint(host, internalPort, "raft")); - ConfigurableEnvironment environment= (ConfigurableEnvironment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); + ConfigurableEnvironment environment = (ConfigurableEnvironment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); String serverRegistryMetadataExternalValue = environment.resolvePlaceholders("${registry.metadata.external:${seata.registry.metadata.external:}}"); if (metadata != null && StringUtils.isNotEmpty(serverRegistryMetadataExternalValue)) { node.updateMetadataWithExternalEndpoints(metadata, node.createExternalEndpoints(serverRegistryMetadataExternalValue)); From 3e034866423efc3ee083272c4aeada3671068907 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sun, 29 Dec 2024 16:08:56 +0800 Subject: [PATCH 07/10] update --- .../apache/seata/common/metadata/Node.java | 29 ++++++++----------- .../server/cluster/raft/RaftStateMachine.java | 4 +-- .../sync/msg/dto/RaftClusterMetadata.java | 12 +++++--- 3 files changed, 22 insertions(+), 23 deletions(-) diff --git a/common/src/main/java/org/apache/seata/common/metadata/Node.java b/common/src/main/java/org/apache/seata/common/metadata/Node.java index f2ed93cf4ec..fc798bf1980 100644 --- a/common/src/main/java/org/apache/seata/common/metadata/Node.java +++ b/common/src/main/java/org/apache/seata/common/metadata/Node.java @@ -20,11 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.seata.common.exception.ParseEndpointException; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.List; -import java.util.ArrayList; +import java.util.*; public class Node { @@ -208,15 +204,11 @@ public List createExternalEndpoints(String external) { for (String s : split) { String[] item = s.split(":"); - if (item.length == 4) { + if (item.length == 3) { try { - String seataHostName = item[0]; - String host = item[1]; - int controllerPort = Integer.parseInt(item[2]); - int transactionPort = Integer.parseInt(item[3]); - if (!seataHostName.equals(System.getenv("SEATA_HOST_NAME"))) { - continue; - } + String host = item[0]; + int controllerPort = Integer.parseInt(item[1]); + int transactionPort = Integer.parseInt(item[2]); externalEndpoints.add(createExternalEndpoint(host, controllerPort, transactionPort)); } catch (NumberFormatException e) { throw new ParseEndpointException("Invalid port number in: " + s); @@ -228,18 +220,21 @@ public List createExternalEndpoints(String external) { return externalEndpoints; } - public void updateMetadataWithExternalEndpoints(Map metadata, List externalEndpoints) { + public Map updateMetadataWithExternalEndpoints(Map metadata, List externalEndpoints) { + Collections.emptyMap(); Object obj = metadata.get("external"); if (obj == null) { if (!externalEndpoints.isEmpty()) { - metadata.put("external", externalEndpoints); - return; + Map metadataMap = new HashMap<>(metadata); + metadataMap.put("external", externalEndpoints); + return metadataMap; } - return; + return metadata; } if (obj instanceof List) { List oldList = (List) obj; oldList.addAll(externalEndpoints); + return metadata; } else { throw new ParseEndpointException("Metadata 'external' is not a List."); } diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java b/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java index a1069232efe..9b49ba011ff 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/RaftStateMachine.java @@ -366,7 +366,7 @@ public RaftClusterMetadata changeOrInitRaftClusterMetadata() { Integer.parseInt( ((Environment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT)) .getProperty("server.port", String.valueOf(7091))), - group, new HashMap<>()); + group, Collections.emptyMap()); leader.setRole(ClusterRole.LEADER); raftClusterMetadata.setLeader(leader); } @@ -406,7 +406,7 @@ private void syncCurrentNodeInfo(PeerId leaderPeerId) { Integer.parseInt( ((Environment)ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT)) .getProperty("server.port", String.valueOf(7091))), - group, new HashMap<>()); + group, Collections.emptyMap()); InvokeContext invokeContext = new InvokeContext(); PutNodeMetadataRequest putNodeInfoRequest = new PutNodeMetadataRequest(node); Configuration configuration = RouteTable.getInstance().getConfiguration(group); diff --git a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java index 808ef4e8c43..7f51ff9efac 100644 --- a/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java +++ b/server/src/main/java/org/apache/seata/server/cluster/raft/sync/msg/dto/RaftClusterMetadata.java @@ -58,11 +58,15 @@ public Node createNode(String host, int txPort, int internalPort, int controlPor node.setVersion(Version.getCurrent()); node.setInternal(node.createEndpoint(host, internalPort, "raft")); ConfigurableEnvironment environment = (ConfigurableEnvironment) ObjectHolder.INSTANCE.getObject(OBJECT_KEY_SPRING_CONFIGURABLE_ENVIRONMENT); - String serverRegistryMetadataExternalValue = environment.resolvePlaceholders("${registry.metadata.external:${seata.registry.metadata.external:}}"); - if (metadata != null && StringUtils.isNotEmpty(serverRegistryMetadataExternalValue)) { - node.updateMetadataWithExternalEndpoints(metadata, node.createExternalEndpoints(serverRegistryMetadataExternalValue)); + String seataRegistryMetadataExternalValue = environment.resolvePlaceholders("${SEATA_REGISTRY_METADATA_EXTERNAL:${seata.registry.metadata.external:}}"); + if (metadata != null) { + if (StringUtils.isNotEmpty(seataRegistryMetadataExternalValue)) { + Map newMetadata = node.updateMetadataWithExternalEndpoints(metadata, node.createExternalEndpoints(seataRegistryMetadataExternalValue)); + Optional.ofNullable(newMetadata).ifPresent(node::setMetadata); + } else { + node.setMetadata(metadata); + } } - Optional.ofNullable(metadata).ifPresent(node::setMetadata); return node; } From 5c4dd14929487322e05ccabf327c9780227937da Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Sun, 29 Dec 2024 16:39:54 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E7=99=BB=E8=AE=B0pr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes/en-us/2.x.md | 4 +++- changes/zh-cn/2.x.md | 3 ++- .../main/java/org/apache/seata/common/metadata/Node.java | 9 +++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 73676753a75..65064389235 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -4,7 +4,8 @@ Add changes here for all PR submitted to the 2.x branch. ### feature: -- [[#PR_NO](https://github.com/seata/seata/pull/PR_NO)] support XXX +- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft mode supports access outside the cluster + ### bugfix: @@ -35,5 +36,6 @@ Thanks to these contributors for their code commits. Please report an unintended - [slievrly](https://github.com/slievrly) - [lyl2008dsg](https://github.com/lyl2008dsg) - [remind](https://github.com/remind) +- [PeppaO](https://github.com/PeppaO) Also, we receive many valuable issues, questions and advices from our community. Thanks for you all. \ No newline at end of file diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 7e3d9a5938c..8dcfc10f455 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -4,7 +4,7 @@ ### feature: -- [[#PR_NO](https://github.com/seata/seata/pull/PR_NO)] 支持XXX +- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft模式支持集群外访问 ### bugfix: @@ -35,5 +35,6 @@ - [slievrly](https://github.com/slievrly) - [lyl2008dsg](https://github.com/lyl2008dsg) - [remind](https://github.com/remind) +- [PeppaO](https://github.com/PeppaO) 同时,我们收到了社区反馈的很多有价值的issue和建议,非常感谢大家。 \ No newline at end of file diff --git a/common/src/main/java/org/apache/seata/common/metadata/Node.java b/common/src/main/java/org/apache/seata/common/metadata/Node.java index fc798bf1980..bcc85a96962 100644 --- a/common/src/main/java/org/apache/seata/common/metadata/Node.java +++ b/common/src/main/java/org/apache/seata/common/metadata/Node.java @@ -19,9 +19,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.seata.common.exception.ParseEndpointException; - -import java.util.*; - +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.List; +import java.util.ArrayList; public class Node { @@ -221,7 +223,6 @@ public List createExternalEndpoints(String external) { } public Map updateMetadataWithExternalEndpoints(Map metadata, List externalEndpoints) { - Collections.emptyMap(); Object obj = metadata.get("external"); if (obj == null) { if (!externalEndpoints.isEmpty()) { From f9f9f324575b1fa0e276c95a0f22b0f00fb2daa3 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Mon, 30 Dec 2024 10:22:26 +0800 Subject: [PATCH 09/10] =?UTF-8?q?pr=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changes/en-us/2.x.md | 2 +- changes/zh-cn/2.x.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md index 65064389235..1ff5b892226 100644 --- a/changes/en-us/2.x.md +++ b/changes/en-us/2.x.md @@ -4,7 +4,7 @@ Add changes here for all PR submitted to the 2.x branch. ### feature: -- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft mode supports access outside the cluster +- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft cluster mode supports address translation ### bugfix: diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md index 8dcfc10f455..f38d504d3fa 100644 --- a/changes/zh-cn/2.x.md +++ b/changes/zh-cn/2.x.md @@ -4,7 +4,7 @@ ### feature: -- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft模式支持集群外访问 +- [[#7069](https://github.com/apache/incubator-seata/pull/7069)] Raft集群模式支持地址转换 ### bugfix: From ff5ff02228510657da111fb9f47f5f86c86c4291 Mon Sep 17 00:00:00 2001 From: PeppaO <2402576196@qq.com> Date: Mon, 30 Dec 2024 11:26:57 +0800 Subject: [PATCH 10/10] add config --- script/client/conf/registry.conf | 4 +++- script/client/spring/application.properties | 4 ++++ script/client/spring/application.yml | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/script/client/conf/registry.conf b/script/client/conf/registry.conf index 1aabbc507f6..d21f03f7232 100644 --- a/script/client/conf/registry.conf +++ b/script/client/conf/registry.conf @@ -18,7 +18,9 @@ registry { # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa、custom、raft、seata type = "file" - + # Supports address translation parameters, currently only supported in raft mode, + # if match the preferredNetworks rule return the first, eg: preferredNetworks = "192.168.*" + preferredNetworks = "" raft { metadata-max-age-ms = 30000 serverAddr = "127.0.0.1:7091" diff --git a/script/client/spring/application.properties b/script/client/spring/application.properties index 2a72d1e5f79..620cbd9714d 100755 --- a/script/client/spring/application.properties +++ b/script/client/spring/application.properties @@ -123,6 +123,10 @@ seata.config.custom.name= seata.registry.type=file +# Supports address translation parameters, currently only supported in raft mode? +# if match the preferredNetworks rule return the first, eg: preferredNetworks = "192.168.*" +seata.registry.preferredNetworks = "" + seata.registry.raft.server-addr= seata.registry.raft.metadata-max-age-ms=30000 seata.registry.raft.username=seata diff --git a/script/client/spring/application.yml b/script/client/spring/application.yml index a6100f05740..580cb0180e0 100755 --- a/script/client/spring/application.yml +++ b/script/client/spring/application.yml @@ -132,6 +132,9 @@ seata: name: registry: type: file + # Supports address translation parameters, currently only supported in raft mode, + # if match the preferredNetworks rule return the first, eg: preferredNetworks = "192.168.*" + preferredNetworks: "" seata: server-addr: 127.0.0.1:8081 namespace: public