Skip to content

Conversation

@YoWuwuuuw
Copy link
Owner

  • I have registered the PR changes.

Ⅰ. Describe what this PR did

Ⅱ. Does this pull request fix one issue?

Ⅲ. Why don't you add test cases (unit test/integration test)?

Ⅳ. Describe how to verify it

Ⅴ. Special notes for reviews

@coderabbitai
Copy link

coderabbitai bot commented Jul 20, 2025

"""

Walkthrough

本次变更在 Seata 项目中引入了客户端路由(routing)功能,并对服务注册、发现、负载均衡等核心机制进行了增强和重构。主要内容包括:新增 ServiceInstance 抽象以替代原有的 InetSocketAddress,实现了基于元数据和地理位置的服务路由与过滤;引入了路由链(RouterChain)、状态路由器(StateRouter)、区域与元数据路由器等扩展点;完善了注册中心接口 RegistryService 及其各实现类的签名和数据结构,全面支持 ServiceInstance;负载均衡策略支持权重、区域、元数据等多种因子;补充了大量单元测试和配置项,Spring Boot 自动配置亦同步适配。涉及核心包有 discovery、common、spring-autoconfigure 及多种注册中心实现。

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant RegistryService
    participant RoutingManager
    participant LoadBalance
    participant ServiceInstance

    Client->>RegistryService: lookup(serviceGroup)
    RegistryService-->>Client: List<ServiceInstance>
    Client->>RoutingManager: filter(List<ServiceInstance>)
    RoutingManager-->>Client: List<ServiceInstance> (filtered)
    Client->>LoadBalance: select(List<ServiceInstance>, xid)
    LoadBalance-->>Client: ServiceInstance
    Client->>ServiceInstance: getAddress(), getMetadata()
Loading
sequenceDiagram
    participant Client
    participant RoutingManager
    participant RegionRouter
    participant MetadataRouter

    Client->>RoutingManager: filter(List<ServiceInstance>)
    RoutingManager->>RegionRouter: route(BitList, RoutingContext)
    RegionRouter-->>RoutingManager: BitList (region filtered)
    RoutingManager->>MetadataRouter: route(BitList, RoutingContext)
    MetadataRouter-->>RoutingManager: BitList (metadata filtered)
    RoutingManager-->>Client: List<ServiceInstance> (final filtered)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120+ 分钟
"""

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch gsoc-routing-support-mock

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@YoWuwuuuw YoWuwuuuw requested a review from Copilot July 20, 2025 16:07
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements "Gsoc routing support mock" by adding comprehensive routing functionality to Seata, including region-based routing and metadata-based filtering capabilities. The changes support service discovery routing with location awareness and dynamic metadata-based server selection.

  • Adds routing framework with region-based and metadata-based routing support
  • Introduces ServiceInstance wrapper for InetSocketAddress with metadata support
  • Updates all registry service implementations to use ServiceInstance instead of InetSocketAddress
  • Adds comprehensive routing configuration properties and Spring Boot autoconfiguration

Reviewed Changes

Copilot reviewed 113 out of 113 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
server/src/main/resources/*.yml Adds server location metadata (lat/lng) configuration for region routing
server/.../VGroupMappingStoreManager.java Updates to use ServiceInstance for registry operations
seata-spring-autoconfigure/.../RoutingProperties.java Adds comprehensive routing configuration properties with metadata router support
discovery/.../RegistryService.java Updates interface to use ServiceInstance instead of InetSocketAddress
discovery/.../routing/** Implements complete routing framework with region and metadata-based routing
script/config-center/config.txt Adds client routing configuration examples
Comments suppressed due to low confidence (1)

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ExpressionParserTest.java:90

  • [nitpick] The comment indicates numbers at start are allowed, but this may not align with typical identifier naming conventions. Consider verifying if this is the intended behavior.
        assertTrue(ExpressionParser.isValidExpression("1version >= 2.3")); // Allow numbers at start

@YoWuwuuuw
Copy link
Owner Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jul 21, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 35

🔭 Outside diff range comments (1)
core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClient.java (1)

288-306: 异常处理优化:区分不同类型的异常

loadBalance 方法捕获所有异常并记录相同的错误消息,建议区分不同类型的异常以便更好地诊断问题。

     protected String loadBalance(String transactionServiceGroup, Object msg) {
         InetSocketAddress address = null;
         try {
             List<ServiceInstance> serviceInstances =
                     RegistryFactory.getInstance().aliveLookup(transactionServiceGroup);

             // Apply routing filter
             serviceInstances = applyRoutingFilter(serviceInstances, transactionServiceGroup, msg);

             address = this.doSelect(serviceInstances, msg);
-        } catch (Exception ex) {
-            LOGGER.error("Select the address failed: {}", ex.getMessage());
+        } catch (FrameworkException ex) {
+            LOGGER.error("Framework error during address selection: {}", ex.getMessage(), ex);
+            throw ex;
+        } catch (Exception ex) {
+            LOGGER.error("Unexpected error during address selection: {}", ex.getMessage(), ex);
         }
         if (address == null) {
             throw new FrameworkException(NoAvailableService);
         }
         return NetUtil.toStringAddress(address);
     }
♻️ Duplicate comments (2)
seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfig.java (1)

23-23: 默认值应为 true 以匹配测试期望

根据过往审查意见,MetadataRouterConfigTest.java 第 32 行期望默认值为 true,当前实现不一致。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ExpressionParserTest.java (1)

114-117: 允许不匹配的括号可能导致混乱的行为

将不匹配的括号作为有效表达式可能会导致混乱的行为。建议将其视为无效语法。

-        assertTrue(ExpressionParser.isValidExpression(
-                "(version >= 2.3")); // Only left parenthesis, treated as part of key-value
-        assertTrue(ExpressionParser.isValidExpression(
-                "version >= 2.3)")); // Only right parenthesis, treated as part of key-value
+        assertFalse(ExpressionParser.isValidExpression(
+                "(version >= 2.3")); // Only left parenthesis, should be invalid
+        assertFalse(ExpressionParser.isValidExpression(
+                "version >= 2.3)")); // Only right parenthesis, should be invalid
🧹 Nitpick comments (43)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java (1)

31-32: Javadoc 已补充,但实现仍使用 InetSocketAddress

当前 PR 的核心方向是引入 ServiceInstance 抽象;该类仍暴露 InetSocketAddress,与整体演进不一致。建议后续一起迁移,或在注释中说明保留原因,以免接口风格混杂。

discovery/seata-discovery-raft/src/test/resources/registry.conf (1)

21-21: 多出的空行可以去除

纯格式变动,对解析无影响,但可保持配置文件紧凑。

discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingRegistryException.java (1)

19-21: Javadoc 动词及措辞微调

当前注释 "Exception thrown when namingserver registry fail." 动词应为第三人称单数;构造器注释漏掉冠词。建议如下修订,更符合英文语法:

- * Exception thrown when namingserver registry fail.
+ * Exception thrown when the naming-server registry fails.
...
-  * Creates an exception with message.
+  * Creates an exception with a message.

Also applies to: 25-26

script/config-center/config.txt (1)

69-93: 路由配置项组织良好!

新增的路由配置项结构清晰,涵盖了启用/禁用、调试模式、回退行为等核心功能。配置示例和注释有助于用户理解和使用。

建议在地理位置坐标配置项后添加单位说明:

-# e.g. 39.9042
+# e.g. 39.9042 (decimal degrees)
 client.routing.location.lat=
-# e.g. 116.4074
+# e.g. 116.4074 (decimal degrees)
 client.routing.location.lng=
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/ServerWithDistance.java (1)

25-41: 不可变数据容器设计优秀

该类作为不可变值对象设计合理:使用 final 字段确保不可变性,泛型类型参数提供灵活性,实现简洁符合标准约定。如果需要在集合中使用或比较对象,可以考虑添加 equals()hashCode()toString() 方法。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/DefaultClientLocationProvider.java (1)

22-33: 实现与注释存在不一致

类注释提到支持降级机制"优先使用动态位置,失败时回退到配置位置",但当前实现仅使用配置的位置信息。建议:

  1. 更新注释以反映当前实现
  2. 或者实现完整的降级机制以支持动态位置获取

另外,建议验证从 RoutingProperties 获取的坐标值是否有效(纬度范围 [-90, 90],经度范围 [-180, 180])。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/RouterChainUtilsTest.java (1)

30-43: 测试覆盖全面,建议增加边界条件测试

测试方法很好地覆盖了路由器名称验证的正面和负面场景。测试逻辑清晰,断言准确。

建议增加一些边界条件测试:

  • 测试包含特殊字符的名称
  • 测试超长名称
  • 测试前后包含空格的名称
@Test
public void testIsValidRouterName() {
    // ... existing tests ...
+   
+   // Additional edge cases
+   assertFalse(RouterChainUtils.isValidRouterName(" region-router"));
+   assertFalse(RouterChainUtils.isValidRouterName("region-router "));
+   assertFalse(RouterChainUtils.isValidRouterName("custom-"));
+   assertFalse(RouterChainUtils.isValidRouterName("metadata-router-"));
}
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChainUtils.java (1)

29-37: 考虑使用常量提升可维护性

当前的路由器名称验证逻辑使用硬编码字符串,建议将这些有效的路由器名称和前缀提取为常量,以提高代码的可维护性和可读性。

+    private static final String REGION_ROUTER = "region-router";
+    private static final String METADATA_ROUTER = "metadata-router";
+    private static final String METADATA_ROUTER_PREFIX = "metadata-router-";
+    private static final String CUSTOM_ROUTER_PREFIX = "custom-";
+
     public static boolean isValidRouterName(String routerName) {
         if (routerName == null) {
             return false;
         }
-        return "region-router".equals(routerName)
-                || "metadata-router".equals(routerName)
-                || routerName.startsWith("metadata-router-") // Support multiple metadata-routers
-                || routerName.startsWith("custom-"); // Allow custom routers
+        return REGION_ROUTER.equals(routerName)
+                || METADATA_ROUTER.equals(routerName)
+                || routerName.startsWith(METADATA_ROUTER_PREFIX) // Support multiple metadata-routers
+                || routerName.startsWith(CUSTOM_ROUTER_PREFIX); // Allow custom routers
     }
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/XIDLoadBalance.java (1)

55-57: 验证类型安全性

当前实现假设所有 invoker 对象都是 ServiceInstance 类型并进行强制转换。虽然根据项目重构上下文这应该是安全的,但建议添加类型检查以提高代码的健壮性。

         for (T invoker : invokers) {
-            InetSocketAddress inetSocketAddress = ((ServiceInstance) invoker).getAddress();
+            if (!(invoker instanceof ServiceInstance)) {
+                continue;
+            }
+            InetSocketAddress inetSocketAddress = ((ServiceInstance) invoker).getAddress();
             if (Objects.equals(xidInetSocketAddress, inetSocketAddress)) {
                 return invoker;
             }
         }
script/client/spring/application.properties (1)

80-81: 添加客户端位置配置的说明

客户端位置坐标为空将禁用基于地理位置的路由功能。建议添加配置格式说明和示例值。

 # Client location configuration for region router
+# Latitude: -90.0 to 90.0, Longitude: -180.0 to 180.0
+# Example: client.routing.location.lat=39.9042, client.routing.location.lng=116.4074
 client.routing.location.lat=
 client.routing.location.lng=
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RoutingManagerTest.java (1)

34-62: 良好的基础测试覆盖率

测试用例很好地覆盖了 RoutingManager 的基本功能,包括单例模式验证和边界条件处理。测试命名清晰,断言恰当。

考虑后续可以添加以下测试场景以提升覆盖率:

  • 路由功能启用/禁用场景的测试
  • 包含真实 ServiceInstance 对象的路由过滤测试
  • 路由失败时的异常处理测试
discovery/seata-discovery-namingserver/src/test/resources/registry.conf (1)

23-25: 建议使用更明显的测试凭据

虽然这是测试配置文件,但建议使用更明显的测试凭据(如 "test-username"/"test-password")以避免意外在生产环境中使用。

-    username = "seata"
-    password = "seata"
+    username = "test-username" 
+    password = "test-password"
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (2)

39-41: 建议增加空值检查

setAttribute 方法应考虑添加 key 的空值检查,提高代码健壮性。

 public void setAttribute(String key, Object value) {
+    if (key == null) {
+        throw new IllegalArgumentException("Key cannot be null");
+    }
     attributes.put(key, value);
 }

48-50: 考虑提供泛型方法重载

为了类型安全,可以考虑添加泛型版本的 getAttribute 方法。

+/**
+ * Get attribute with type casting
+ * @param key key  
+ * @param type expected type
+ * @return typed value
+ */
+@SuppressWarnings("unchecked")
+public <T> T getAttribute(String key, Class<T> type) {
+    Object value = attributes.get(key);
+    return value != null && type.isInstance(value) ? (T) value : null;
+}
discovery/seata-discovery-redis/src/test/java/org/apache/seata/discovery/registry/redis/RedisRegisterServiceImplTest.java (1)

104-104: 断言逻辑正确但可能存在脆弱性

断言检查集合大小的逻辑正确,但直接访问集合可能在多线程环境中存在竞态条件风险。

考虑添加同步机制或使用不可变集合快照进行断言:

-Assertions.assertEquals(1, CLUSTER_INSTANCE_MAP.get("cluster").size());
+Set<ServiceInstance> clusterInstances = CLUSTER_INSTANCE_MAP.get("cluster");
+Assertions.assertEquals(1, clusterInstances != null ? clusterInstances.size() : 0);

Also applies to: 112-112

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/PrimaryBackupRouterChainTest.java (2)

32-79: 基础测试覆盖良好,建议考虑增加更多场景

当前测试用例覆盖了 PrimaryBackupRouterChain 的基本功能和边界条件:

  • 构造函数测试
  • 空列表和 null 输入处理
  • 路由器顺序验证

测试实现正确,边界条件处理得当。

建议考虑添加以下测试场景以提供更全面的覆盖:

@Test
public void testFilterAllWithActualServers() {
    // 测试实际服务实例的过滤逻辑
}

@Test 
public void testRouterChainIntegration() {
    // 测试与实际路由器的集成
}

@Test
public void testComplexRouterOrderScenarios() {
    // 测试更复杂的路由器顺序配置场景
}

32-79: 测试覆盖主要场景,结构清晰

该测试类为 PrimaryBackupRouterChain 提供了良好的测试覆盖:

测试场景完整:

  • 构造函数基本功能
  • 空列表和null值边界条件处理
  • 路由器顺序配置验证

测试质量良好:

  • 测试方法命名清晰描述测试意图
  • 使用合适的断言方法
  • 边界条件测试确保健壮性

建议考虑添加更多功能性测试,如实际的服务实例过滤场景。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/WeightedRandomLoadBalance.java (3)

74-76: 优化默认返回逻辑

当权重选择逻辑未能选中任何实例时,直接返回第一个元素可能不够理想。建议改为使用随机选择以保持负载均衡的随机性。

-    return invokers.get(0);
+    return RANDOM_LOAD_BALANCE.select(invokers, xid);

119-139: 完善权重提取的错误处理

权重提取逻辑在处理无效字符串时的错误处理可以进一步优化,确保在各种边界情况下都能正确工作。

考虑添加更详细的日志记录:

                } else if (weightObj instanceof String) {
                    try {
                        weight = Integer.parseInt((String) weightObj);
                    } catch (NumberFormatException e) {
+                        // Log warning for invalid weight format
+                        LOGGER.warn("Invalid weight format for service instance: {}, using default weight", weightObj);
                        return DEFAULT_WEIGHT;
                    }
                }

26-33: 文档完善

类级别的 Javadoc 很好地说明了权重规则。建议增加一些使用示例。

/**
 * The type Weighted random load balance(based on metadata).
 *
 * Weight rules:
 * - Only supports non-negative weights (>= 0)
 * - Weight can be configured in metadata with key "weight" as Number or String
 * - Default weight is 1 if not specified
+ *
+ * Example usage:
+ * ServiceInstance instance = new ServiceInstance(address);
+ * instance.getMetadata().put("weight", 5);
 */
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcherTest.java (1)

117-123: 建议增加更多数值精度测试用例

当前的精度测试较为基础,建议增加更复杂的数值比较场景。

考虑添加以下测试用例:

@Test
public void testComplexNumericPrecision() {
    ServiceInstance server = mock(ServiceInstance.class);
    RoutingContext ctx = mock(RoutingContext.class);
    Map<String, Object> metadata = new HashMap<>();
    metadata.put("version", "2.10");
    when(server.getMetadata()).thenReturn(metadata);

    // Test version comparison edge cases
    ConfigurableConditionMatcher matcher = new ConfigurableConditionMatcher("version > 2.9");
    assertTrue(matcher.match(server, ctx));
    
    matcher = new ConfigurableConditionMatcher("version < 2.11");
    assertTrue(matcher.match(server, ctx));
}
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java (1)

57-57: 日志级别不当

当客户端位置信息缺失时,使用了 LOGGER.error,但这并非严重错误,因为代码已经优雅地处理了这种情况(返回原始服务器列表)。建议使用 LOGGER.warnLOGGER.info

-            LOGGER.error("Failed to get client location, skipping region router");
+            LOGGER.warn("Failed to get client location, skipping region router");
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java (1)

61-63: 代码优化:使用 StringUtils 进行空字符串检查

为了保持代码风格的一致性,建议使用项目中已有的 StringUtils 工具类。

-        // If expression is empty or contains only spaces, return original server list directly
-        if (expression == null || expression.trim().isEmpty()) {
+        // If expression is empty or contains only spaces, return original server list directly
+        if (StringUtils.isBlank(expression)) {
             return servers;
         }
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/loadbalance/LoadBalanceFactoryTest.java (1)

38-50: 测试资源管理改进

MockedStatic 资源应该使用 try-with-resources 或确保在异常情况下也能正确关闭。

 public class LoadBalanceFactoryTest {

-    private MockedStatic<ConfigurationFactory> mockedConfigurationFactory;
-
-    @BeforeEach
-    public void setUp() {
-        mockedConfigurationFactory = mockStatic(ConfigurationFactory.class);
-    }
-
-    @AfterEach
-    public void tearDown() {
-        if (mockedConfigurationFactory != null) {
-            mockedConfigurationFactory.close();
-        }
-    }

     @Test
     public void testGetInstance() {
-        Configuration mockConfig = mock(Configuration.class);
-        mockedConfigurationFactory.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
-
-        when(mockConfig.getConfig(eq("client.loadBalance.type"), anyString())).thenReturn("XID");
-
-        LoadBalance loadBalance = LoadBalanceFactory.getInstance();
-        assertInstanceOf(XIDLoadBalance.class, loadBalance);
+        try (MockedStatic<ConfigurationFactory> mockedConfigurationFactory = mockStatic(ConfigurationFactory.class)) {
+            Configuration mockConfig = mock(Configuration.class);
+            mockedConfigurationFactory.when(ConfigurationFactory::getInstance).thenReturn(mockConfig);
+
+            when(mockConfig.getConfig(eq("client.loadBalance.type"), anyString())).thenReturn("XID");
+
+            LoadBalance loadBalance = LoadBalanceFactory.getInstance();
+            assertInstanceOf(XIDLoadBalance.class, loadBalance);
+        }
     }
 }
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/AbstractStateRouter.java (2)

98-98: 日志性能优化:使用参数化日志

避免在日志语句中使用字符串连接,应使用参数化日志以提高性能。

-        LOGGER.info("Using fallback strategy for router " + routerName);
+        LOGGER.info("Using fallback strategy for router {}", routerName);

64-68: 性能优化:避免不必要的列表转换

在调试模式下,result.toList() 会创建一个新的列表。如果快照不需要实际的列表内容,可以考虑延迟转换或使用其他方式记录。

如果 RouterSnapshotNode 只是用于记录和调试,可以考虑传递 BitList 的引用或仅记录必要的信息,而不是转换整个列表。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/MetadataRouterTest.java (1)

91-143: 测试改进:使用参数化测试减少重复代码

多个测试方法具有相似的结构,可以使用 JUnit 5 的参数化测试来减少代码重复并提高可维护性。

@ParameterizedTest
@MethodSource("provideExpressionsAndExpectedResults")
public void testDoRouteWithVariousExpressions(String expression, 
                                              Map<String, Map<String, Object>> serverMetadata,
                                              Set<String> expectedServers) {
    MetadataRouter router = new MetadataRouter();
    router.setExpression(expression);
    
    List<ServiceInstance> servers = new ArrayList<>();
    Map<String, ServiceInstance> serverMap = new HashMap<>();
    
    for (Map.Entry<String, Map<String, Object>> entry : serverMetadata.entrySet()) {
        ServiceInstance server = mock(ServiceInstance.class);
        when(server.getMetadata()).thenReturn(entry.getValue());
        servers.add(server);
        serverMap.put(entry.getKey(), server);
    }
    
    BitList<ServiceInstance> serversBitList = BitList.fromList(servers);
    RoutingContext ctx = new RoutingContext();
    
    BitList<ServiceInstance> result = router.doRoute(serversBitList, ctx);
    assertEquals(expectedServers.size(), result.size());
    
    for (String expectedServer : expectedServers) {
        assertTrue(result.toList().contains(serverMap.get(expectedServer)));
    }
}

private static Stream<Arguments> provideExpressionsAndExpectedResults() {
    return Stream.of(
        Arguments.of("version >= 2.0", 
                     Map.of("server1", Map.of("version", "2.5"),
                            "server2", Map.of("version", "1.5")),
                     Set.of("server1")),
        Arguments.of("env = prod",
                     Map.of("server1", Map.of("env", "prod"),
                            "server2", Map.of("env", "dev")),
                     Set.of("server1"))
        // 添加更多测试用例
    );
}
core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClient.java (1)

332-343: 防御性编程:添加空列表检查的日志

虽然方法已经处理了空列表的情况,但建议在返回 null 之前添加警告日志,以便于问题排查。

     protected InetSocketAddress doSelect(List<ServiceInstance> list, Object msg) throws Exception {
         if (CollectionUtils.isNotEmpty(list)) {
             if (list.size() > 1) {
                 return LoadBalanceFactory.getInstance()
                         .select(list, getXid(msg))
                         .getAddress();
             } else {
                 return list.get(0).getAddress();
             }
         }
+        LOGGER.warn("No available service instances for selection");
         return null;
     }
discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java (1)

69-69: 字段类型更新为 ServiceInstance 列表。

类型更改正确,但字段名 clusterAddressMap 现在可能会产生误导,因为它存储的是 ServiceInstance 对象而不仅仅是地址。考虑重命名以提高清晰度。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/RegionRouterTest.java (1)

38-42: 建议增强构造函数测试的覆盖范围

当前测试仅验证了对象创建成功,建议添加对默认配置值的验证,例如 regionTopN 的默认值。

 @Test
 public void testConstructor() {
     RegionRouter router = new RegionRouter();
     assertNotNull(router);
+    // Verify default configuration values
+    String snapshot = router.buildSnapshot();
+    assertTrue(snapshot.contains("regionTopN=5")); // Assuming default is 5
 }
discovery/seata-discovery-sofa/src/main/java/org/apache/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java (1)

192-204: 考虑保留潜在的元数据信息

当前实现只使用地址创建 ServiceInstance,没有包含元数据。如果 SOFA 注册中心支持元数据,建议考虑保留。

如果未来需要支持元数据,可以扩展此方法以包含元数据信息:

 private List<ServiceInstance> flatData(Map<String, List<String>> instances) {
     List<ServiceInstance> result = new ArrayList<>();
 
     for (Map.Entry<String, List<String>> entry : instances.entrySet()) {
         for (String str : entry.getValue()) {
             String ip = StringUtils.substringBeforeLast(str, HOST_SEPERATOR);
             String port = StringUtils.substringAfterLast(str, HOST_SEPERATOR);
             InetSocketAddress inetSocketAddress = new InetSocketAddress(ip, Integer.parseInt(port));
-            result.add(new ServiceInstance(inetSocketAddress));
+            // 如果有元数据,可以在这里添加
+            Map<String, Object> metadata = new HashMap<>();
+            metadata.put("zone", entry.getKey()); // 例如:将 zone 信息作为元数据
+            result.add(new ServiceInstance(inetSocketAddress, metadata));
         }
     }
     return result;
 }
discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplMockTest.java (2)

144-185: 建议使用更具描述性的测试方法名

测试实现良好,但方法名 testHandleMetadata_withMockResponse 不够具体。建议改为描述具体测试场景。

-public void testHandleMetadata_withMockResponse() throws Exception {
+public void testHandleMetadata_shouldReturnServiceInstancesFromLeaderNode() throws Exception {

211-223: 建议增强刷新存活查找的测试覆盖

当前测试只验证了传入的实例列表,建议测试 refreshAliveLookup 方法的实际效果,例如验证内部状态的更新。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingProperties.java (2)

77-85: 建议添加地理坐标的格式验证

经纬度使用字符串类型便于配置,但建议在设置时进行格式验证,确保是有效的数值。

可以考虑添加验证注解或在 setter 方法中进行验证:

@Pattern(regexp = "^[-+]?([1-8]?\\d(\\.\\d+)?|90(\\.0+)?)$", message = "Invalid latitude format")
private String locationLat = "";

@Pattern(regexp = "^[-+]?(180(\\.0+)?|((1[0-7]\\d)|([1-9]?\\d))(\\.\\d+)?)$", message = "Invalid longitude format")
private String locationLng = "";

155-166: 建议增强元数据路由器管理方法的健壮性

getMetadataRouter 可能返回 null,建议调用方进行 null 检查。addMetadataRouter 会覆盖已存在的配置,建议在文档中明确说明此行为。

考虑返回 Optional 或提供默认值:

 public MetadataRouterConfig getMetadataRouter(String routerName) {
-    return metadataRouters.get(routerName);
+    return metadataRouters.getOrDefault(routerName, new MetadataRouterConfig());
 }

或者添加检查方法:

public boolean hasMetadataRouter(String routerName) {
    return metadataRouters.containsKey(routerName);
}
discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java (1)

224-268: 建议简化地址字符串处理逻辑

当前的地址字符串拼接逻辑较为复杂,建议提取辅助方法以提高可读性。

 addressList = stream.map(instance -> {
-    String host = NetUtil.toStringHost(instance.getAddress());
-    Node node = map.get(host
-            + IP_PORT_SPLIT_CHAR
-            + instance.getAddress().getPort());
+    String instanceKey = toInstanceKey(instance);
+    Node node = map.get(instanceKey);
     InetSocketAddress controlEndpoint = null;
     if (node != null) {
         controlEndpoint = selectControlEndpoint(node);
     }
-    return host
-            + IP_PORT_SPLIT_CHAR
-            + (controlEndpoint != null
-                    ? controlEndpoint.getPort()
-                    : instance.getAddress().getPort());
+    return toAddressString(instance, controlEndpoint);
 })
 .collect(Collectors.toList());

建议添加以下辅助方法:

private static String toInstanceKey(ServiceInstance instance) {
    return NetUtil.toStringHost(instance.getAddress()) 
        + IP_PORT_SPLIT_CHAR 
        + instance.getAddress().getPort();
}

private static String toAddressString(ServiceInstance instance, InetSocketAddress controlEndpoint) {
    String host = NetUtil.toStringHost(instance.getAddress());
    int port = controlEndpoint != null 
        ? controlEndpoint.getPort() 
        : instance.getAddress().getPort();
    return host + IP_PORT_SPLIT_CHAR + port;
}
core/src/test/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClientTest.java (1)

129-455: 测试覆盖全面,场景设计合理

测试用例覆盖了区域路由、元数据路由、主备路由等多种场景,验证逻辑清晰。

不过建议考虑添加以下边界测试场景:

  • 路由过滤后结果为空的情况
  • 多个路由器组合使用的场景
  • 路由配置格式错误的容错测试
discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplTest.java (4)

67-67: 修正注释中的拼写错误

注释中的 "based on it" 应该是 "based on its"。

-                "unit1"); // vGroup -> unitName, namingserver automatically adds transaction groups based on it
+                "unit1"); // vGroup -> unitName, namingserver automatically adds transaction groups based on its

122-141: 测试逻辑正确,但 API 设计可能引起混淆

测试实现正确。注释说明了传入的 ServiceInstance 参数实际上没有被使用,而是使用全局单例 Instance.getInstance()。这种 API 设计可能会让调用者感到困惑。


164-195: Watch 测试实现全面但可以改进

测试覆盖了无变化和有变化两种场景,逻辑正确。但存在以下改进点:

  1. 使用 Thread.sleep 可能导致测试不稳定
  2. 通过反射直接修改字段较为脆弱

考虑使用更可靠的同步机制替代 Thread.sleep,例如使用 CountDownLatchCompletableFuture


197-208: 减少测试中的等待时间

测试逻辑正确,但 2 秒的等待时间似乎过长。考虑减少等待时间或使用更精确的同步机制。

-        Thread.sleep(2000);
+        Thread.sleep(100);
discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImpl.java (1)

201-206: API 设计可能引起混淆

register 方法接受 ServiceInstance 参数但实际不使用它,而是使用全局的 Instance.getInstance()。这种设计可能会让调用者困惑。

考虑要么移除未使用的参数,要么修改实现以使用传入的参数。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ExpressionParser.java (1)

53-71: 主解析方法实现合理,但需要完善空白字符处理

解析逻辑清晰,包含了适当的null检查、格式验证和委托模式。不过在第58行,应该检查trim后的表达式是否为空,避免处理仅包含空白字符的表达式。

建议优化:

 String trimmedExpression = expression.trim();
+
+if (trimmedExpression.isEmpty()) {
+    return Collections.emptyList();
+}
 
-// Validate expression format
-if (!isValidExpression(trimmedExpression)) {
+if (!isValidExpression(trimmedExpression)) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 608785f and 90eb1cb.

📒 Files selected for processing (107)
  • changes/en-us/2.x.md (1 hunks)
  • changes/zh-cn/2.x.md (1 hunks)
  • common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1 hunks)
  • common/src/test/java/org/apache/seata/common/metadata/ServiceInstanceTest.java (1 hunks)
  • core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClient.java (4 hunks)
  • core/src/main/java/org/apache/seata/core/rpc/netty/NettyClientChannelManager.java (5 hunks)
  • core/src/main/java/org/apache/seata/core/rpc/netty/NettyServerBootstrap.java (3 hunks)
  • core/src/test/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClientTest.java (1 hunks)
  • discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java (7 hunks)
  • discovery/seata-discovery-consul/src/test/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImplMockTest.java (2 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/ConsistentHashLoadBalance.java (3 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LeastActiveLoadBalance.java (2 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LoadBalance.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LoadBalanceFactory.java (2 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/RandomLoadBalance.java (0 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/RoundRobinLoadBalance.java (0 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/WeightedRandomLoadBalance.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/XIDLoadBalance.java (2 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/FileRegistryServiceImpl.java (3 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryHeartBeats.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryProvider.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryService.java (5 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryType.java (0 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RouterSnapshotNode.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingManager.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/StateRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/DefaultRouterChain.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/PrimaryBackupRouterChain.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChain.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChainUtils.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/config/RoutingProperties.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConditionMatcher.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcher.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ExpressionParser.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/ClientLocationProvider.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/DefaultClientLocationProvider.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/GeoLocation.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/ServerWithDistance.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/AbstractStateRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/main/resources/META-INF/services/org.apache.seata.discovery.routing.StateRouter (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/config/ConfigurationFactoryTest.java (0 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/loadbalance/LoadBalanceFactoryTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/loadbalance/LoadBalanceTest.java (2 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/FileRegistryProviderTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/FileRegistryServiceImplTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/MultiRegistryFactoryTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryProvider.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryService.java (3 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/BitListTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RouterSnapshotNodeTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RoutingContextTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RoutingManagerTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/DefaultRouterChainTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/PrimaryBackupRouterChainTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/RouterChainUtilsTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcherTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ExpressionParserTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/DefaultClientLocationProviderTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/GeoLocationTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/ServerWithDistanceTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/AbstractStateRouterTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/MetadataRouterTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/RegionRouterTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/resources/META-INF/services/org.apache.seata.discovery.registry.RegistryProvider (1 hunks)
  • discovery/seata-discovery-core/src/test/resources/file.conf (1 hunks)
  • discovery/seata-discovery-core/src/test/resources/registry.conf (0 hunks)
  • discovery/seata-discovery-custom/src/test/java/org/apache/seata/discovery/registry/custom/CustomRegistryServiceForTest.java (1 hunks)
  • discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java (10 hunks)
  • discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java (5 hunks)
  • discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplTest.java (7 hunks)
  • discovery/seata-discovery-eureka/src/main/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java (7 hunks)
  • discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImplTest.java (6 hunks)
  • discovery/seata-discovery-eureka/src/test/resources/registry.conf (0 hunks)
  • discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java (8 hunks)
  • discovery/seata-discovery-nacos/src/test/java/org/apache/seata/discovery/registry/nacos/NacosRegistryServiceImplTest.java (0 hunks)
  • discovery/seata-discovery-nacos/src/test/resources/registry.conf (0 hunks)
  • discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingListener.java (1 hunks)
  • discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingRegistryException.java (1 hunks)
  • discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryProvider.java (1 hunks)
  • discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImpl.java (16 hunks)
  • discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryProviderTest.java (1 hunks)
  • discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplMockTest.java (1 hunks)
  • discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplTest.java (3 hunks)
  • discovery/seata-discovery-namingserver/src/test/resources/registry.conf (1 hunks)
  • discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java (12 hunks)
  • discovery/seata-discovery-raft/src/test/resources/registry.conf (2 hunks)
  • discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java (11 hunks)
  • discovery/seata-discovery-redis/src/test/java/org/apache/seata/discovery/registry/redis/RedisRegisterServiceImplTest.java (3 hunks)
  • discovery/seata-discovery-sofa/src/main/java/org/apache/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java (8 hunks)
  • discovery/seata-discovery-zk/src/main/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java (11 hunks)
  • discovery/seata-discovery-zk/src/test/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java (6 hunks)
  • discovery/seata-discovery-zk/src/test/resources/registry.conf (1 hunks)
  • script/client/spring/application.properties (1 hunks)
  • script/client/spring/application.yml (1 hunks)
  • script/config-center/config.txt (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java (3 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfig.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingProperties.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfigTest.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingPropertiesTest.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java (2 hunks)
⛔ Files not processed due to max files limit (6)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataPropertiesTest.java
  • server/src/main/java/org/apache/seata/server/cluster/raft/RaftServerManager.java
  • server/src/main/java/org/apache/seata/server/storage/raft/store/RaftVGroupMappingStoreManager.java
  • server/src/main/java/org/apache/seata/server/store/VGroupMappingStoreManager.java
  • server/src/main/resources/application.example.yml
  • server/src/main/resources/application.raft.example.yml
💤 Files with no reviewable changes (8)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/RandomLoadBalance.java
  • discovery/seata-discovery-nacos/src/test/java/org/apache/seata/discovery/registry/nacos/NacosRegistryServiceImplTest.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryType.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/RoundRobinLoadBalance.java
  • discovery/seata-discovery-core/src/test/resources/registry.conf
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/config/ConfigurationFactoryTest.java
  • discovery/seata-discovery-nacos/src/test/resources/registry.conf
  • discovery/seata-discovery-eureka/src/test/resources/registry.conf
🧰 Additional context used
🧠 Learnings (4)
discovery/seata-discovery-raft/src/test/resources/registry.conf (1)

Learnt from: YoWuwuuuw
PR: #27
File: discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/AbstractNacosRegistryServiceImpl.java:219-223
Timestamp: 2025-07-07T11:25:46.633Z
Learning: 在 Seata 的 Nacos 注册服务实现中,RAM 角色名称配置 (ramRoleName) 使用 FILE_ROOT_CONFIG 而不是 FILE_ROOT_REGISTRY 是原始设计逻辑,这是有意为之的,因为 RAM 角色认证被视为通用配置而非注册中心特定配置。

discovery/seata-discovery-zk/src/test/resources/registry.conf (1)

Learnt from: YoWuwuuuw
PR: #27
File: discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/AbstractNacosRegistryServiceImpl.java:219-223
Timestamp: 2025-07-07T11:25:46.633Z
Learning: 在 Seata 的 Nacos 注册服务实现中,RAM 角色名称配置 (ramRoleName) 使用 FILE_ROOT_CONFIG 而不是 FILE_ROOT_REGISTRY 是原始设计逻辑,这是有意为之的,因为 RAM 角色认证被视为通用配置而非注册中心特定配置。

discovery/seata-discovery-namingserver/src/test/resources/registry.conf (1)

Learnt from: YoWuwuuuw
PR: #27
File: discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/AbstractNacosRegistryServiceImpl.java:219-223
Timestamp: 2025-07-07T11:25:46.633Z
Learning: 在 Seata 的 Nacos 注册服务实现中,RAM 角色名称配置 (ramRoleName) 使用 FILE_ROOT_CONFIG 而不是 FILE_ROOT_REGISTRY 是原始设计逻辑,这是有意为之的,因为 RAM 角色认证被视为通用配置而非注册中心特定配置。

discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java (1)

Learnt from: YoWuwuuuw
PR: #27
File: discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/AbstractNacosRegistryServiceImpl.java:219-223
Timestamp: 2025-07-07T11:25:46.633Z
Learning: 在 Seata 的 Nacos 注册服务实现中,RAM 角色名称配置 (ramRoleName) 使用 FILE_ROOT_CONFIG 而不是 FILE_ROOT_REGISTRY 是原始设计逻辑,这是有意为之的,因为 RAM 角色认证被视为通用配置而非注册中心特定配置。

🧬 Code Graph Analysis (27)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/MultiRegistryFactoryTest.java (1)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryService.java (1)
  • MockNacosRegistryService (28-49)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/XIDLoadBalance.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-zk/src/test/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-zk/src/main/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java (1)
  • ZookeeperRegisterServiceImpl (61-446)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/ConsistentHashLoadBalance.java (1)
config/seata-config-core/src/main/java/org/apache/seata/config/ConfigurationFactory.java (1)
  • ConfigurationFactory (43-363)
discovery/seata-discovery-consul/src/test/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImplMockTest.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConditionMatcher.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/chain/RouterChainUtilsTest.java (1)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChainUtils.java (1)
  • RouterChainUtils (22-38)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LeastActiveLoadBalance.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-redis/src/test/java/org/apache/seata/discovery/registry/redis/RedisRegisterServiceImplTest.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
common/src/main/java/org/apache/seata/common/util/NetUtil.java (1)
  • NetUtil (41-411)
core/src/main/java/org/apache/seata/core/rpc/netty/NettyServerBootstrap.java (4)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
common/src/main/java/org/apache/seata/common/XID.java (1)
  • XID (25-110)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/MultiRegistryFactory.java (1)
  • MultiRegistryFactory (37-85)
common/src/main/java/org/apache/seata/common/metadata/Instance.java (1)
  • Instance (28-187)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java (5)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1)
  • BitList (30-97)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/config/RoutingProperties.java (1)
  • RoutingProperties (24-210)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/GeoLocation.java (1)
  • GeoLocation (23-44)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/ServerWithDistance.java (1)
  • ServerWithDistance (25-41)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/BitListTest.java (1)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1)
  • BitList (30-97)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChain.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryService.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-custom/src/test/java/org/apache/seata/discovery/registry/custom/CustomRegistryServiceForTest.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcher.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcherTest.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
common/src/main/java/org/apache/seata/common/util/NetUtil.java (1)
  • NetUtil (41-411)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/DefaultClientLocationProvider.java (1)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/config/RoutingProperties.java (1)
  • RoutingProperties (24-210)
discovery/seata-discovery-eureka/src/main/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java (1)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/AbstractStateRouter.java (3)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1)
  • BitList (30-97)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RouterSnapshotNode.java (1)
  • RouterSnapshotNode (26-107)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
common/src/main/java/org/apache/seata/common/util/NetUtil.java (1)
  • NetUtil (41-411)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/MetadataRouterTest.java (3)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1)
  • BitList (30-97)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)
  • RoutingContext (25-51)
discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java (3)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
common/src/main/java/org/apache/seata/common/util/StringUtils.java (1)
  • StringUtils (42-446)
common/src/main/java/org/apache/seata/common/util/CollectionUtils.java (1)
  • CollectionUtils (30-362)
discovery/seata-discovery-zk/src/main/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
common/src/main/java/org/apache/seata/common/util/NetUtil.java (1)
  • NetUtil (41-411)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/config/RoutingProperties.java (1)
config/seata-config-core/src/main/java/org/apache/seata/config/ConfigurationFactory.java (1)
  • ConfigurationFactory (43-363)
discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RoutingManagerTest.java (2)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)
  • ServiceInstance (33-135)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingManager.java (1)
  • RoutingManager (35-133)
🔇 Additional comments (241)
discovery/seata-discovery-core/src/test/resources/META-INF/services/org.apache.seata.discovery.registry.RegistryProvider (1)

17-17: 服务提供者路径更新正确

已将 SPI 条目调整到 mock 子包,能够正确匹配 MockNacosRegistryProvider 的新包名,保证 ServiceLoader 加载无误。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/MultiRegistryFactoryTest.java (1)

26-26: 引入 MockNacosRegistryService 的 import 合理

单测中确实在第 104 行使用了该类,新增 import 保证编译通过,无其他问题。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryProvider.java (1)

23-23: 仅添加空行,功能无影响

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryProvider.java (1)

17-32: 包名与引入调整符合 mock 测试场景,代码简洁 ✅

变更后包路径、更名及新增 import 均正确匹配 mock 实现,未发现功能或规范问题。

changes/zh-cn/2.x.md (1)

21-23: 更新 changelog 条目,信息清晰 ✅

已明确记录 PR apache#7533 的功能点,文档一致性良好。

discovery/seata-discovery-core/src/test/resources/file.conf (1)

26-33: 新增 service 配置段看起来合理

配置键符合 Seata HOCON 语法;仅提醒确认 default.grouplist 单节点限制符合测试预期,生产如需多节点请另行处理。

seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/StarterConstants.java (1)

39-39: 确认 ROUTING_PREFIX 常量已被引用

已在以下位置使用该常量,无“写而不用”问题:

  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java:PROPERTY_BEAN_MAP.put(ROUTING_PREFIX, RoutingProperties.class)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingProperties.java:@ConfigurationProperties(prefix = ROUTING_PREFIX)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LoadBalance.java (1)

29-34: 文档改进很好!

Javadoc 注释的更新提高了接口的清晰度,明确指定了处理 ServiceInstances 对象和返回 ServiceInstance 类型,与整个项目向 ServiceInstance 抽象迁移的重构保持一致。

changes/en-us/2.x.md (1)

23-23: 变更日志更新准确!

PR 引用格式正确,功能描述准确地反映了基于元数据的注册发现和 namingserver 类型支持,与整个重构工作一致。

discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingListener.java (1)

19-27: 接口文档完善得很好!

NamingListener 接口和 onEvent 方法添加的 Javadoc 注释清晰地解释了接口的用途和参数含义,提高了代码的可维护性和可读性。

discovery/seata-discovery-core/src/main/resources/META-INF/services/org.apache.seata.discovery.routing.StateRouter (1)

17-18: SPI 配置文件已验证,格式和实现类均正确

  • 已确认 RegionRouter 实现类存在于
    discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java
  • 已确认 MetadataRouter 实现类存在于
    discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java
  • 已确认 StateRouter 接口定义存在于
    discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/StateRouter.java

以上类均正确实现了 StateRouter 接口,SPI 配置无误,批准合并。

discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplTest.java (2)

26-26: 正确添加了 ServiceInstance 导入!

为支持新的服务实例抽象添加了必要的导入。


72-72: ServiceInstance 已完整支持 InetSocketAddress 等效功能

经验证,ServiceInstancecommon/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java 中提供了:

  • 接收 InetSocketAddress 的构造函数(含带/不带 metadata 参数两种重载)
  • getAddress() / setAddress(InetSocketAddress) 方法
  • 静态转换方法 convertToServiceInstanceSet(List<InetSocketAddress>)convertToServiceInstanceSet(Set<InetSocketAddress>)
  • 静态工厂方法 fromStringMap(InetSocketAddress, Map<String,String>)

测试中对 registerunregisterlookup 的调用均正确使用了这一抽象,无需额外修改。

discovery/seata-discovery-consul/src/test/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImplMockTest.java (3)

23-23: 正确引入了 ServiceInstance 类

导入语句正确添加,与整个项目从 InetSocketAddress 迁移到 ServiceInstance 抽象的重构保持一致。


80-80: ServiceInstance 创建方式正确

使用简单的构造函数创建 ServiceInstance,只传入地址而不包含元数据,这对于测试场景是合适的。


83-87: 方法调用已正确更新为使用 ServiceInstance

register() 和 unregister() 方法调用已正确更新为接受 ServiceInstance 参数,与新的 API 签名保持一致。测试逻辑保持完整性。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/FileRegistryProviderTest.java (1)

22-31: 简洁有效的提供者测试实现

测试类结构良好,正确验证了 FileRegistryProvider 返回 FileRegistryServiceImpl 实例。测试覆盖了提供者的核心功能,与其他注册中心提供者测试保持一致的模式。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/ClientLocationProvider.java (1)

22-28: 设计良好的位置提供者接口

接口设计简洁明确,遵循单一职责原则。方法签名清晰,文档完整,为基于地理位置的路由功能提供了良好的抽象基础。接口设计具有良好的可扩展性。

discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryProviderTest.java (1)

22-31: 标准的注册中心提供者测试实现

测试类结构规范,包含完整的类级别文档。测试方法正确验证了 NamingserverRegistryProvider 返回正确的服务实现类型,与其他注册中心提供者测试保持一致的测试模式。

discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryProvider.java (2)

23-25: 类级别文档添加得当

为 NamingserverRegistryProvider 类添加了简洁明确的 Javadoc 注释,准确描述了类的用途,提升了代码的可维护性。


29-33: 方法文档规范完整

为 provide() 方法添加了标准的 Javadoc 注释,包含了方法功能描述和返回值说明,遵循了良好的文档编写规范。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/RouterChain.java (1)

24-37: 良好的接口设计!

该接口设计简洁明确,很好地体现了单一职责原则。方法签名清晰,适合在路由场景中实现责任链模式。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConditionMatcher.java (1)

22-34: 接口设计规范!

该接口为路由条件匹配提供了清晰的契约,方法签名合理,文档说明简洁明了。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/ConsistentHashLoadBalance.java (3)

40-43: 文档改进很好!

增强了虚拟节点字段的文档说明,使配置的作用更加清晰。


64-68: 内部类文档完善!

ConsistentHashSelectorWrapper 类添加了详细的文档说明,清楚地解释了其缓存选择器实例的作用。


106-112: 完善的类型参数文档!

ConsistentHashSelector 类添加了详细的文档说明,特别是泛型参数的说明,提高了代码可读性。

discovery/seata-discovery-etcd3/src/test/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImplMockTest.java (5)

34-34: 正确导入新的抽象类!

添加了 ServiceInstance 的导入,配合API重构的需要。


166-166: 测试方法更新正确!

将注册方法的参数从直接使用 InetSocketAddress 更新为使用 ServiceInstance 封装,与API重构保持一致。


184-184: 注销方法测试更新一致!

注销方法的参数同样更新为使用 ServiceInstance,保持了API的一致性。


203-207: 查找方法返回类型更新正确!

将返回类型从 List<InetSocketAddress> 更新为 List<ServiceInstance>,并正确调整了地址提取逻辑。


222-222: 方法签名简化合理!

移除了 throws Exception 声明,简化了方法签名。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/SeataClientEnvironmentPostProcessor.java (3)

28-28: 导入语句符合规范

新增的 RoutingProperties 导入语句遵循现有代码的组织结构,与其他客户端属性类的导入保持一致。


45-45: 静态导入符合现有模式

ROUTING_PREFIX 静态导入的位置和格式与其他前缀常量的导入保持一致。


72-72: 属性映射注册实现正确

路由属性的注册遵循了现有的模式,确保 Spring Boot 能够正确绑定路由配置属性到 RoutingProperties 类。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RoutingContextTest.java (3)

29-37: 测试方法结构良好

该测试方法正确验证了 RoutingContext 的基本属性设置和获取功能,使用不同数据类型测试泛型处理能力,测试覆盖充分。


42-46: 边界情况测试完善

测试不存在属性的访问行为,验证返回 null 的正确性,这是重要的防御性编程测试用例。


51-58: 属性覆盖测试逻辑清晰

该测试有效验证了属性覆盖机制,确保相同键的多次设置能正确更新值,测试逻辑简洁明了。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/DefaultClientLocationProviderTest.java (1)

29-38: 测试覆盖度良好

测试方法正确验证了客户端位置提供者的基本功能:

  • 确保返回非空的 GeoLocation 对象
  • 验证经纬度坐标在有效地理范围内(纬度 [-90, 90],经度 [-180, 180])
  • 测试逻辑清晰,断言使用恰当
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LoadBalanceFactory.java (2)

29-29: 常量简化改进了可读性

LOAD_BALANCE_TYPE 直接赋值为字符串常量简化了代码结构,提高了可读性。


41-41: 新增加权随机负载均衡支持

新增的 WEIGHTED_RANDOM_LOAD_BALANCE 常量为系统提供了基于权重的随机负载均衡能力,与新的 ServiceInstance 抽象配合良好。

discovery/seata-discovery-zk/src/test/resources/registry.conf (1)

26-31: 测试配置简化合理

将测试配置简化为仅包含文件和 ZooKeeper 注册中心类型,有利于专注测试 ZooKeeper 注册服务的 ServiceInstance 集成。配置参数设置合理。

core/src/main/java/org/apache/seata/core/rpc/netty/NettyServerBootstrap.java (2)

203-207: ServiceInstance 迁移实现正确

将服务注册从直接使用 Instance 改为创建 ServiceInstance 对象的方式是正确的。代码正确地从 Instance 的 transaction 端点提取地址信息,并保留了元数据,与新的服务发现架构保持一致。


224-229: 服务注销逻辑一致性良好

服务注销时同样使用 ServiceInstance,与注册逻辑保持一致。正确地处理了多注册中心场景,确保所有注册中心都能正确注销服务实例。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfig.java (1)

34-46: Builder 模式实现规范

流式构建器方法实现正确,返回 this 引用支持方法链式调用,符合 Java Bean 规范。

discovery/seata-discovery-namingserver/src/test/resources/registry.conf (1)

20-26: 配置结构变更符合架构重构需求

从 "namingserver" 到 "seata" 类型的变更与 ServiceInstance 抽象化重构保持一致,简化了配置结构。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/GeoLocationTest.java (3)

30-34: 浮点数比较使用 delta 值是正确做法

测试中使用 0.0001 作为浮点数比较的精度阈值,避免了浮点数精度问题,是良好的测试实践。


40-46: toString 方法测试覆盖全面

测试验证了字符串格式包含经纬度值和 "Location" 关键词,确保输出格式正确性。


52-56: 负坐标测试增强了代码健壮性

专门测试负坐标值的处理,提高了对南纬西经等真实地理坐标的测试覆盖。

discovery/seata-discovery-eureka/src/test/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImplTest.java (4)

24-24: ServiceInstance 导入支持架构迁移

正确导入了 ServiceInstance 类以支持从原始 InetSocketAddress 到 ServiceInstance 抽象的迁移。


83-83: 字段重命名反映数据结构变更

从 CLUSTER_ADDRESS_MAP 重命名为 CLUSTER_INSTANCE_MAP,准确反映了从存储地址到存储服务实例的数据结构变更。


97-97: ServiceInstance 包装保持测试逻辑一致性

测试方法中正确使用 ServiceInstance 包装 InetSocketAddress,保持了原有测试逻辑的完整性。

Also applies to: 108-108, 157-157


176-186: 查找方法返回类型更新正确

lookup 方法返回类型从 List 更新为 List,测试断言相应调整,保持了类型安全性。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingContext.java (1)

27-27: 使用 ConcurrentHashMap 确保线程安全

选择 ConcurrentHashMap 作为属性存储结构,在多线程路由环境中提供了必要的线程安全保障。

discovery/seata-discovery-redis/src/test/java/org/apache/seata/discovery/registry/redis/RedisRegisterServiceImplTest.java (4)

19-19: 正确添加了 ServiceInstance 导入

导入语句正确添加,支持从 InetSocketAddress 到 ServiceInstance 的迁移。


70-71: ServiceInstance 构造和注册逻辑正确

测试正确创建 ServiceInstance 对象并调用注册方法,符合新的抽象设计。


75-75: 注销方法调用正确

正确使用 ServiceInstance 对象进行服务注销操作。


93-96: 类型匹配已确认,CLUSTER_INSTANCE_MAP 反射转换安全
RedisRegistryServiceImpl 中的

private static final ConcurrentMap<String, Set<ServiceInstance>> CLUSTER_INSTANCE_MAP = new ConcurrentHashMap<>();

与测试里通过反射取出并强转为 ConcurrentMap<String, Set<ServiceInstance>> 完全一致,类型安全,无需修改。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/LeastActiveLoadBalance.java (2)

20-20: 正确添加了 ServiceInstance 导入

导入语句正确添加,支持负载均衡器使用新的 ServiceInstance 抽象。


41-43: ServiceInstance 转换和地址获取正确

正确将调用者转换为 ServiceInstance 并通过 getAddress().toString() 获取地址用于 RpcStatus 查询,保持了与现有 RPC 状态管理的兼容性。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RouterSnapshotNode.java (2)

26-51: 优秀的不可变快照类设计

类设计良好,使用 final 字段确保不可变性,构造函数参数完整,自动生成时间戳。泛型设计提供了良好的类型安全性和灵活性。


102-106: toString 方法实现良好

toString 方法提供了清晰的格式化输出,包含所有关键信息,有利于调试和日志记录。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/region/ServerWithDistanceTest.java (3)

32-40: 基础功能测试覆盖完整

测试正确验证了构造函数和 getter 方法的基本功能,断言逻辑清晰准确。


45-50: 空值处理测试设计良好

正确测试了 null 服务器的处理情况,确保类能够正确处理边界条件。


55-72: 边界值测试覆盖全面

测试涵盖了零距离和负距离的场景,确保类对各种数值输入都能正确处理。边界值测试很重要,特别是在地理距离计算中。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/BitListTest.java (4)

34-38: 基础创建测试正确

测试正确验证了从列表创建 BitList 的功能和初始大小。


55-63: 过滤测试逻辑正确

测试正确验证了过滤功能,条件表达式和结果断言都很准确。


69-75: 空状态测试覆盖完整

测试涵盖了空列表和非空列表的情况,验证了 isEmpty() 方法的正确性。


81-84: 大小测试简洁有效

测试正确验证了 size() 方法返回正确的元素数量。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfigTest.java (2)

26-76: 测试覆盖全面,代码质量良好!

该测试类为 MetadataRouterConfig 提供了全面的单元测试覆盖,包括:

  • 默认值验证
  • 属性设置和获取
  • 流式 API 支持
  • 复杂表达式处理
  • 边界条件(空值和 null 值)

测试用例设计合理,遵循了良好的测试实践。


1-77: 测试覆盖率完整,实现良好

该测试类为 MetadataRouterConfig 提供了全面的单元测试覆盖,包括:

  • 默认值验证
  • 属性设置和获取
  • 流式API测试
  • 复杂表达式处理
  • 边界条件(空值和null值)

测试方法命名清晰,每个测试专注于特定功能点,符合单元测试最佳实践。

discovery/seata-discovery-zk/src/test/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImplTest.java (10)

23-23: 正确添加了 ServiceInstance 导入

正确导入了新的 ServiceInstance 类,支持从 InetSocketAddress 到更丰富的服务实例抽象的迁移。


60-60: 服务实例获取方式更新正确

使用 getInstance() 方法获取单例实例,替代了之前通过 ZookeeperRegistryProvider 的方式,与实现类的重构保持一致。


82-82: 服务注册和注销调用已正确更新

所有的 register()unregister() 方法调用都已更新为使用 ServiceInstance 包装器,而不是直接使用 InetSocketAddress。这与新的服务实例抽象保持一致。

Also applies to: 124-124


147-151: 查找方法返回类型和断言已正确更新

lookup() 方法现在返回 List<ServiceInstance> 而不是 List<InetSocketAddress>,断言也相应更新为比较 ServiceInstance 对象。迁移实现正确。


155-221: 字段命名在接口中已统一,无需修改

在 RegistryService 接口中已统一声明并使用 CURRENT_INSTANCE_MAP,全局搜索未发现任何 CURRENT_ADDRESS_MAP 的残留引用,ZookeeperRegisterServiceImpl 直接继承并正确使用该静态字段,测试用例引用也一致。


23-23: ServiceInstance 抽象迁移正确

正确导入了新的 ServiceInstance 类,这是从原始 InetSocketAddress 向更丰富的服务实例抽象迁移的一部分。


60-60: 单例获取方式更新正确

使用 getInstance() 方法获取 ZookeeperRegisterServiceImpl 实例,与实现类的重构保持一致。


82-82: ServiceInstance 在测试方法中使用一致

在 register、lookup 和 unregister 操作中正确使用 ServiceInstance 包装 InetSocketAddress,与新的服务注册接口签名保持一致。

Also applies to: 90-90, 124-124


147-151: 断言更新符合新的数据结构

正确更新了断言逻辑,比较 List<ServiceInstance> 而不是原来的 InetSocketAddress 列表,确保测试验证逻辑与重构后的接口一致。


155-221: 测试用例全面更新以支持 ServiceInstance

所有相关测试方法都已正确更新:

  • CURRENT_INSTANCE_MAP 替代了原来的地址映射
  • 方法参数和返回值类型更新为 ServiceInstance
  • 断言逻辑相应调整

这确保了测试覆盖率在重构后保持完整。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/StateRouter.java (2)

27-64: 接口设计优秀,为路由框架奠定了坚实基础

StateRouter<T> 接口设计遵循了良好的面向对象设计原则:

  • 泛型设计:使用泛型参数 T 提供了类型安全性和灵活性
  • 性能优化:使用 BitList<T> 作为参数避免了不必要的列表复制操作
  • 职责链模式:通过 setNext()/getNext() 方法支持路由器链式组合
  • 运行时区分isRuntime() 方法区分配置型和动态计算型路由器
  • 调试支持buildSnapshot() 和快照参数支持路由过程的可观测性
  • 上下文传递RoutingContext 参数支持基于请求上下文的路由决策

该接口为元数据路由、区域路由等具体实现提供了统一的抽象,是整个路由框架的核心组件。


21-64: 路由接口设计优秀

StateRouter<T> 接口设计体现了多个良好的设计原则:

优点:

  • 泛型设计提供类型安全和灵活性
  • 责任链模式支持组合多个路由器
  • isRuntime() 方法区分配置型和运行时路由器,有助于性能优化
  • 调试模式和快照功能支持故障排查
  • 文档注释清晰完整

设计模式应用:

  • 责任链模式:setNext()/getNext() 方法
  • 策略模式:不同的路由实现
  • 装饰器模式:通过链式组合增强功能

该接口为整个路由框架奠定了坚实的基础。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (2)

30-55: 设计理念优秀,使用 BitSet 提升性能

BitList<T> 类的设计很好地平衡了性能和功能需求:

  • 使用 BitSet 避免复制底层列表,提升了过滤操作的性能
  • 泛型设计提供类型安全性
  • 静态工厂方法 fromList() 符合良好的 API 设计实践

30-97: BitList 设计理念优秀但需修复关键问题

优点:

  • 基于 BitSet 的高性能设计理念正确
  • 避免复制底层列表,内存效率高
  • 泛型设计提供类型安全

需要修复的问题:

  • filter 方法的位复制逻辑错误
  • toList 方法的性能问题

修复这些问题后,该类将成为路由框架中的高效核心组件。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ExpressionParser.java (10)

53-71: 解析方法实现正确,逻辑清晰

主要解析方法的实现很好:

  • 正确处理了空值和空表达式的情况
  • 在解析前进行了格式验证,避免了后续错误
  • 清晰地区分了单一表达式和OR逻辑表达式

151-189: 单一表达式验证逻辑实现完善

验证逻辑很全面:

  • 正确处理括号的移除(仅当两端都有括号时)
  • 严格验证表达式必须有三个部分:键、操作符、值
  • 合理的键名验证(不能为空或包含空格)
  • 完整的操作符白名单验证
  • 值不能为空的检查

所有验证规则都符合文档描述的语法要求。


226-234: 操作符验证采用白名单机制,安全可靠

操作符验证实现很好:

  • 使用严格的相等性检查,避免了任何注入风险
  • 覆盖了所有文档中提到的操作符
  • 拒绝任何其他操作符组合,提高了安全性

45-45: 正则表达式模式简单有效

使用的正则表达式\\(([^()]+)\\)简单而有效,能够正确匹配括号内的内容,且不会匹配嵌套括号,符合当前的表达式语法要求。


25-42: 类文档详细完整,提供了清晰的使用指导

文档质量很高:

  • 详细说明了支持的语法和操作符
  • 提供了两种模式的清晰示例
  • 重要的AND逻辑限制说明很有价值
  • 示例格式清晰易懂,有助于用户正确使用

131-144: 验证方法实现正确

主验证入口逻辑清晰,正确处理了空表达式情况,并适当委托给专门的验证方法。空表达式被视为有效的设计决策与解析方法保持一致。


151-189: 单表达式验证实现优秀

验证逻辑非常全面且正确:

  • 仅移除最外层括号的处理方式正确(第154-157行)
  • 对key、operator、value的验证都很严格
  • 使用helper方法isValidOperator提高了代码可维护性
  • 边界情况处理得当

这个方法展示了正确的括号处理方式,建议在parseSingleExpression中采用相同的方法。


196-219: OR表达式验证逻辑严格且合理

验证实现很好地强制要求每个OR表达式部分都必须有括号,并重用了单表达式验证逻辑。这种严格的格式要求有助于防止格式错误的表达式。

注意:此方法与之前评论的parseOrExpression方法存在逻辑不一致的问题需要解决。


226-234: 操作符验证实现正确且安全

使用严格的字符串相等性检查而不是复杂的模式匹配,覆盖了所有文档中提到的操作符。"严格匹配,拒绝任何其他组合"的设计思路有助于提高安全性。


241-243: OR表达式检测方法简单有效

实现简洁明了,适合当前支持的表达式格式。虽然没有考虑引号内的"|"字符,但鉴于当前表达式格式的简单性,这种实现是可接受的。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingPropertiesTest.java (8)

35-53: 默认值测试覆盖全面且断言合理

测试方法很好地验证了所有属性的默认值:

  • 合理的默认配置(启用状态为false,回退为true)
  • 正确验证了集合属性的初始状态
  • 使用了适当的断言方法

58-98: 元数据路由器测试用例设计完整

测试方法设计得很好:

  • 测试数据真实合理(版本、环境、区域表达式)
  • 覆盖了启用和禁用两种状态
  • 验证了添加、检索和不存在情况的处理
  • 断言逻辑清晰,测试覆盖面广

103-132: 属性设置和获取测试验证充分

测试正确验证了所有setter和getter方法:

  • 使用与默认值不同的测试数据,确保setter生效
  • 覆盖了所有属性类型(布尔、字符串、整数)
  • 测试数据具有现实意义(地理坐标、路由配置)

137-163: 流式API测试设计优秀

流式API测试实现得很好:

  • 正确验证了方法链式调用的返回值和属性设置
  • 使用了真实的地理坐标数据(北京和上海的经纬度)
  • 测试数据组合合理,体现了实际使用场景

35-53: 默认值测试覆盖全面

测试方法全面验证了RoutingProperties的所有默认值,包括布尔标志、字符串值和数值。测试断言合理且完整。


58-98: 动态元数据路由器测试完备

测试全面覆盖了动态元数据路由器功能:

  • 测试多个路由器配置的添加和检索
  • 验证启用和禁用状态的处理
  • 测试不存在路由器的null返回
  • 表达式配置的验证

测试用例设计合理,覆盖了关键的功能场景。


103-132: 属性设置和获取测试标准完整

测试覆盖了所有的setter和getter方法,使用与默认值不同的测试值来确保设置方法正确工作。测试实现规范,验证了所有属性的设置和获取功能。


137-163: 流式API测试设计良好

测试有效验证了流式API的方法链调用功能,确保链式调用能够正确设置所有属性值。测试值的选择合理,断言全面验证了流式模式的正确性。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/mock/MockNacosRegistryService.java (3)

17-44: Mock实现成功迁移到ServiceInstance抽象

重构实现得很好:

  • 包路径调整到mock子目录,组织结构更清晰
  • 导入和方法签名正确更新为使用ServiceInstance
  • 保持了mock行为的一致性(空方法实现,返回空列表)
  • 与整个代码库的ServiceInstance抽象迁移保持一致

这个变更符合从InetSocketAddress到ServiceInstance的整体重构目标。


17-23: 包结构和导入更新正确

包名迁移到mock子包合理,导入语句正确更新为使用新的ServiceInstance抽象,符合整体重构的方向。


31-45: 方法签名更新与整体重构一致

所有相关方法的签名都正确更新为使用ServiceInstance而不是InetSocketAddress,与其他注册服务实现的重构保持一致。Mock实现的空操作行为得到正确保留。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/FileRegistryServiceImpl.java (4)

60-75: 方法签名更新正确对齐ServiceInstance抽象

方法签名的更新很好:

  • register和unregister方法正确更新为使用ServiceInstance参数
  • 添加了close方法的空实现,符合接口要求
  • lookup方法返回类型更新为ServiceInstance列表
  • 对于基于文件的注册服务,空的方法实现是合适的

83-89: lookup方法正确实现ServiceInstance转换

ServiceInstance对象创建实现得当:

  • 保持了现有的端点解析逻辑不变
  • 正确使用ServiceInstance构造函数创建对象
  • 适当地处理了从字符串地址到ServiceInstance的转换
  • 维持了与基于文件配置的向后兼容性

实现很好地桥接了旧的配置格式和新的ServiceInstance抽象。


19-19: 方法签名和接口更新正确

导入语句和方法签名的更新与其他注册服务实现保持一致,正确迁移到ServiceInstance抽象。新增的close方法提供了空实现,符合接口要求。

Also applies to: 60-63, 72-75


83-90: lookup方法实现更新正确

正确地将返回类型从List<InetSocketAddress>更改为List<ServiceInstance>,并在循环中构造ServiceInstance对象。使用接受InetSocketAddress参数的构造函数是正确的选择。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcher.java (8)

34-46: 构造函数的条件解析逻辑实现正确

构造函数设计得很好:

  • 简单有效的空格分割解析逻辑
  • 严格验证必须有三个部分(键、操作符、值)
  • 适当的错误处理,格式不正确时抛出IllegalArgumentException
  • 清晰的字段存储结构

48-58: 匹配方法实现了良好的防御性编程

match方法实现得很好:

  • 正确处理元数据获取和空值检查
  • 合理的策略:当属性不存在时返回false而不是抛出异常
  • 适当地将Object类型的元数据值转换为字符串进行比较
  • 清晰的职责分离,将比较逻辑委托给专门的方法

60-104: 值比较逻辑设计合理,处理全面

比较方法实现得很好:

  • 等值操作符(= 和 !=)智能支持数值和字符串两种比较模式
  • 关系操作符(>, >=, <, <=)仅支持数值比较,设计合理
  • 完善的NumberFormatException错误处理
  • 对无效操作符和解析失败返回false的策略恰当

双重比较模式的设计很智能,先尝试数值比较,失败时回退到字符串比较。


107-113: toString方法提供了完整的调试信息

toString实现很有用:

  • 包含了所有关键字段的详细信息
  • 使用了适当的字符串格式化,便于调试
  • 为日志记录和问题排查提供了有价值的信息

34-46: 构造函数解析逻辑基本正确

条件字符串的解析实现简单直接,适合当前的简单表达式格式。不过解析逻辑假设值中不包含空格,对于更复杂的使用场景可能需要增强(如支持引号包围的值)。


48-58: 匹配方法实现逻辑合理

ServiceInstance元数据中获取值的逻辑正确,对缺失键的处理(返回false)符合过滤场景的需求。将比较逻辑委托给compareValues方法体现了良好的关注点分离。


60-104: 比较值方法实现完善

比较逻辑设计合理:

  • 对等值操作符(=、!=)智能地从数值比较回退到字符串比较
  • 关系操作符(>、<、>=、<=)仅支持数值比较,符合预期
  • NumberFormatException的处理得当
  • 对无效情况返回false的错误处理策略合适

实现覆盖了预期的使用场景,逻辑清晰可靠。


106-113: toString方法实现标准

提供了包含所有解析组件的详细字符串表示,有助于调试和日志记录。实现符合标准做法。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcherTest.java (1)

32-176: 测试覆盖率全面,实现良好

测试类提供了全面的覆盖,包括:

  • 构造函数验证和异常处理
  • 字符串和数值比较的各种操作符
  • 精度处理和边界情况
  • 缺失元数据的处理
  • 无效数值比较的处理

测试结构清晰,使用了适当的模拟对象,测试方法命名具有描述性。

discovery/seata-discovery-custom/src/test/java/org/apache/seata/discovery/registry/custom/CustomRegistryServiceForTest.java (1)

19-55: ServiceInstance 迁移实现正确

代码已正确地从 InetSocketAddress 迁移到 ServiceInstance,与整个项目的架构重构保持一致。方法签名更新恰当,移除了 throws Exception 声明符合接口简化的趋势。

作为测试模拟服务,所有方法都抛出 UnsupportedOperationException 是合理的实现。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/RouterSnapshotNodeTest.java (2)

29-179: 测试实现全面且结构良好

测试类为 RouterSnapshotNode<T> 提供了全面的单元测试覆盖:

  1. 核心功能测试:验证所有字段的正确初始化和获取
  2. 边界情况:处理空列表、null 值等边界场景
  3. 泛型支持:验证不同类型的泛型支持
  4. 时间戳验证:确保时间戳在合理范围内
  5. 字符串表示:验证 toString 方法的格式化输出

测试方法命名清晰,断言恰当,很好地支持了路由框架的调试和分析功能。


118-121: 时间戳测试逻辑优秀

时间戳验证逻辑很好地确保了时间戳的准确性,使用1秒的容差范围是合理的选择,既避免了测试的脆弱性又保证了时间戳的有效性。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/registry/FileRegistryServiceImplTest.java (3)

43-161: 测试覆盖全面,但需要改进配置测试的隔离性

测试类为 FileRegistryServiceImpl 提供了全面的覆盖,包括注册、查找、存活实例刷新和离线地址移除等核心功能。使用 ServiceInstance 对象保持了与项目架构迁移的一致性。


48-50: 测试实例创建合理

使用不同IP地址创建的 ServiceInstance 实例为测试场景提供了良好的数据基础,有助于验证各种操作的正确性。


146-160: 改进反射测试的隔离性

当前的反射测试虽然正确恢复了配置实例,但可能存在线程安全问题或影响其他并发测试。

建议使用更安全的测试方式:

@Test
public void testLookup() throws Exception {
    List<ServiceInstance> lookup = fileRegistryService.lookup(TEST_CLUSTER);
    assertEquals(serviceInstance1, lookup.get(0));

-    // Set the getServiceGroup() to return null by reflection
-    Configuration mockConfig = Mockito.mock(Configuration.class);
-    when(mockConfig.getConfig("service.vgroupMapping.default_tx_group")).thenReturn(null);
-    Field configField = ConfigurationFactory.class.getDeclaredField("instance");
-    configField.setAccessible(true);
-    Object originalConfigInstance = configField.get(null);
-    configField.set(null, mockConfig);
-
-    try {
-        assertThrows(ConfigNotFoundException.class, () -> fileRegistryService.lookup(TEST_CLUSTER));
-    } finally {
-        // reset ConfigurationFactory.instance
-        configField.set(null, originalConfigInstance);
-    }
+}

+@Test
+public void testLookupWithMissingConfig() {
+    // Use a non-existent cluster name to trigger ConfigNotFoundException
+    assertThrows(ConfigNotFoundException.class, () -> 
+        fileRegistryService.lookup("non_existent_cluster"));

Likely an incorrect or invalid review comment.

core/src/main/java/org/apache/seata/core/rpc/netty/NettyClientChannelManager.java (2)

237-281: ServiceInstance 重构实现正确

将地址列表从 List<String> 迁移到 List<ServiceInstance> 的重构实现得当。保留了向后兼容性,通过 NetUtil.toStringAddress() 转换地址用于通道管理。


314-323: getAvailServerList 方法简化得当

方法返回类型从 List<String> 改为 List<ServiceInstance> 后,代码更加简洁清晰。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/resources/META-INF/additional-spring-configuration-metadata.json (1)

321-406: 路由配置元数据定义完善

新增的路由配置属性结构清晰,命名规范统一。默认值设置合理(如 enabled=false 确保向后兼容)。位置坐标使用 lat/lng 格式符合地理位置标准。

discovery/seata-discovery-redis/src/main/java/org/apache/seata/discovery/registry/redis/RedisRegistryServiceImpl.java (3)

155-190: register 和 unregister 方法重构正确

方法签名更新为接收 ServiceInstance 参数,实现中正确提取 InetSocketAddress 进行实际的注册/注销操作,保持了向后兼容性。


232-269: lookup 方法实现正确

返回类型更新为 List<ServiceInstance>,订阅回调中正确处理了从地址字符串到 ServiceInstance 的转换。


363-392: updateClusterAddressMap 方法重构得当

方法先收集 InetSocketAddress 集合,然后使用工具方法转换为 ServiceInstance 集合,实现清晰且高效。

common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)

114-129: equals 和 hashCode 实现正确

使用 Objects.equalsObjects.hash 的标准实现,正确包含了 address 和 metadata 字段。

discovery/seata-discovery-eureka/src/main/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java (12)

30-30: 导入 ServiceInstance 类支持新的抽象层。

这个导入是必要的,用于支持从 InetSocketAddress 迁移到更丰富的 ServiceInstance 抽象。


73-73: 字段类型更新以支持 ServiceInstance 抽象。

CLUSTER_ADDRESS_MAP 更名为 CLUSTER_INSTANCE_MAP 并将值类型从 List<InetSocketAddress> 更改为 List<ServiceInstance>,这与整体重构保持一致。


98-99: 方法签名更新以使用 ServiceInstance 参数。

正确地从 ServiceInstance 中提取地址进行注册。虽然当前实现没有使用 ServiceInstance 的元数据,但这可能是 Eureka 特定实现的设计选择。


110-110: 取消注册方法签名更新保持一致性。

与注册方法保持一致的参数类型更改。


118-118: 订阅方法移除了检查异常声明。

确保内部异常处理仍然适当,或者操作确实不再需要抛出检查异常。


124-124: 取消订阅方法移除了检查异常声明。

与订阅方法保持一致的签名更改。


136-136: 查找方法返回类型更新为 ServiceInstance 列表。

与整体重构保持一致的返回类型更改。


155-155: 返回新的集群实例映射中的数据。

正确地从更新后的 CLUSTER_INSTANCE_MAP 返回服务实例列表。


171-182: 刷新集群方法正确转换为 ServiceInstance。

方法正确地将 Eureka 的 InstanceInfo 对象转换为 ServiceInstance 列表:

  • 过滤状态为 UP 且地址和端口有效的实例
  • 使用工具方法进行类型转换
  • 更新集群映射并处理离线地址

转换逻辑完整且正确。


30-30: ServiceInstance 抽象引入得当

新增的 ServiceInstance 导入支持了从原始 InetSocketAddress 到更丰富的服务实例抽象的迁移,这将支持基于元数据的路由和负载均衡功能。


73-73: 集群映射数据结构升级合理

CLUSTER_ADDRESS_MAP 重命名为 CLUSTER_INSTANCE_MAP 并改为存储 List<ServiceInstance> 而不是 List<InetSocketAddress>,这个改变与整体架构迁移保持一致。


98-107: 注册方法签名更新正确

register 方法现在接受 ServiceInstance 参数并提取其地址信息,这种封装方式保持了向后兼容性,同时支持了元数据传递。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingManager.java (7)

39-39: 单例模式实现正确使用双检锁。

使用 volatile 关键字和双检锁模式确保线程安全的懒加载单例实现,符合标准实践。

Also applies to: 63-72


47-57: 构造函数基于配置选择路由链实现。

构造函数逻辑清晰,根据配置选择合适的路由链实现并记录模式。静态配置依赖可能会影响测试灵活性,但对于应用级单例是可接受的。


79-108: 过滤方法具有良好的防御性编程和错误处理。

方法实现了多重安全保障:

  • 优雅处理空输入
  • 配置检查避免不必要处理
  • 异常处理回退到原始服务列表
  • 可配置的调试日志

确保了路由失败时的服务可用性。


114-132: 上下文创建方法正确设置路由上下文信息。

方法正确地构建包含客户端位置、路由器配置和时间戳的路由上下文,支持地理位置路由和配置检查。空值处理得当。


35-72: 单例模式实现正确

RoutingManager 使用了正确的双重检查锁定单例模式,线程安全性得到保证。构造函数中基于配置选择路由链的设计也很合理。


79-108: 路由过滤方法设计良好

filter 方法的实现考虑了多种边界情况:

  • 空列表检查
  • 路由功能开关检查
  • 异常处理与降级策略(返回原始服务列表)
  • 调试日志支持

这种设计确保了路由功能的健壮性。


114-132: 路由上下文创建完整

createRoutingContext 方法正确地构建了路由上下文,包含了客户端位置信息、路由器配置标志和时间戳等关键信息,为后续的路由决策提供了充分的上下文数据。

discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java (10)

127-128: 注册方法正确提取 ServiceInstance 中的地址。

与其他注册实现保持一致的参数类型更改。


140-141: 取消注册方法保持一致的实现模式。

与注册方法类似的正确实现。


147-147: 订阅方法移除检查异常声明。

与 Eureka 实现保持一致的签名简化。


160-160: 取消订阅方法签名更改保持一致性。


168-168: 查找方法返回类型更新为 ServiceInstance 列表。


178-178: 按集群查找方法返回类型正确更新。


321-328: 刷新集群方法正确转换 Consul 服务为 ServiceInstance。

方法正确地将 Consul 的 HealthService 对象转换为 ServiceInstance 列表,转换逻辑与其他注册实现保持一致。


25-25: ServiceInstance 导入一致性良好

与其他注册中心实现保持一致,正确引入了 ServiceInstance 抽象类。


69-69: 集群地址映射类型更新正确

clusterAddressMap 的类型从 ConcurrentMap<String, List<InetSocketAddress>> 更新为 ConcurrentMap<String, List<ServiceInstance>>,与架构迁移目标一致。


321-329: Consul 服务转换逻辑正确

从 Consul HealthService 转换为 ServiceInstance 的逻辑正确:先提取服务地址信息转为 InetSocketAddress,再通过 ServiceInstance.convertToServiceInstanceSet 工具方法转换。这种两步转换保证了数据的正确性。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/AbstractStateRouterTest.java (12)

39-60: 测试路由器实现为测试抽象类提供了良好的模式。

内部 TestRouter 类设计良好:

  • 使用简单的 String 泛型类型
  • 可配置行为支持不同测试场景
  • 正确实现抽象方法
  • 为测试目的提供有意义的输出

这是测试抽象类的良好实践。


65-69: 构造函数测试提供基础验证。

简单但必要的测试,确保构造函数正常工作。


74-81: 运行时标志测试正确验证路由器类型区分。

测试正确验证了运行时标志功能,这对于区分路由框架中不同类型的路由器很重要。


86-94: 路由器链测试验证责任链模式实现。

测试验证了责任链模式的实现,这对于路由框架将多个路由器链接在一起的能力至关重要。


99-109: 正常路由流程测试覆盖成功路径。

测试覆盖了路由执行的正常路径,确保路由正常工作时结果正确。


114-125: 空结果回退测试验证关键的容错行为。

这是验证路由过滤掉所有服务器时回退行为的关键测试。回退到原始服务器列表对于维护服务可用性很重要。


131-149: 调试模式测试全面验证快照生成功能。

测试验证了调试/跟踪功能,这对于生产环境中排查路由问题至关重要。测试全面检查了快照生成的所有方面。


154-166: 链式路由测试验证端到端责任链模式。

测试确保责任链模式的端到端工作,验证多个路由器可以串联执行。


171-177: 快照构建测试验证输出格式。

测试确保 buildSnapshot 方法正确工作并生成有意义的输出。


39-60: 测试路由器实现设计良好

TestRouter 内部类提供了灵活的测试实现:

  • 支持配置路由器名称、运行时标志和结果行为
  • doRoute 方法可以模拟正常和空结果场景
  • buildSnapshot 方法提供了简单但有效的快照实现

这种设计支持了多种测试场景的验证。


114-125: 回退策略测试完整

空结果场景测试验证了路由器的回退机制:当路由结果为空时,系统应该返回原始服务列表而不是空列表。这是一个重要的容错设计,测试覆盖得当。


130-149: 调试模式测试覆盖充分

调试模式测试验证了快照生成功能的各个方面:

  • 快照数量正确(1个)
  • 路由器名称记录正确
  • 输入输出大小记录正确
  • 选中的服务器列表正确
  • 快照内容包含预期信息

这确保了调试功能的可靠性。

discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java (14)

31-31: 添加 ServiceInstance 导入支持重构。

与其他注册实现保持一致的导入添加。


94-94: 字段类型正确更新同时保持修订版本跟踪。

更改正确地将 Pair 中的值类型更新为使用 ServiceInstance,同时保持 etcd 所需的修订版本跟踪机制。


135-136: 注册方法正确采用 ServiceInstance 参数。

与其他注册实现保持一致的重构模式。


156-157: 取消注册方法保持一致的参数类型。


173-173: 订阅方法移除检查异常声明。

与其他注册实现的异常处理简化保持一致。


180-180: 取消订阅方法签名简化。


193-193: 查找方法返回类型更新为 ServiceInstance 列表。


203-203: 按集群查找方法正确处理 Pair 结构。

实现正确地从 Pair 结构中提取 ServiceInstance 列表,同时适当处理空值情况。

Also applies to: 226-227


281-287: 刷新集群方法正确处理 etcd 特定要求。

方法正确地处理 etcd 特定的要求:

  • 从 etcd 键值对中提取实例信息
  • 解析 IP 和端口
  • 使用工具方法转换为 ServiceInstance
  • 在 Pair 结构中维护修订版本跟踪

实现与 etcd 数据模型和整体重构保持一致。


442-442: EtcdWatcher 正确适配 ServiceInstance 类型。

EtcdWatcher 更新正确地适配了新的 ServiceInstance 类型,同时保持 etcd 所需的基于修订版本的监视功能。


31-31: ServiceInstance 导入与其他实现一致

正确导入 ServiceInstance,与 Eureka、Consul 等其他注册中心实现保持一致的迁移模式。


94-94: Etcd 特有的版本控制设计合理

使用 Pair<Long, List<ServiceInstance>> 存储修订版本和服务实例列表,这种设计考虑了 Etcd 的版本控制机制,是合适的架构选择。


281-291: Etcd 键值转换逻辑正确

从 Etcd 键值对转换为 ServiceInstance 的流程正确:

  1. 提取键值对中的地址信息
  2. 解析为 InetSocketAddress
  3. 使用 ServiceInstance.convertToServiceInstanceSet 转换
  4. 与修订版本一起存储

转换逻辑与其他注册中心实现保持一致。


442-442: EtcdWatcher 适配 ServiceInstance 正确

EtcdWatcher 中正确使用了新的数据结构 Pair<Long, List<ServiceInstance>>,确保监听器能够获取到正确的修订版本信息用于增量更新。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/RegionRouterTest.java (6)

47-53: 测试方法实现合理

快照构建测试验证了必要的信息输出。


85-95: 边界条件测试实现正确

正确测试了无客户端位置信息时的回退行为。


100-112: 异常输入处理测试合理

正确测试了无效位置信息的容错处理。


117-141: 位置排序测试实现完善

正确验证了基于地理位置的服务实例排序功能。


146-169: 服务器位置信息缺失处理测试完善

正确测试了混合场景:部分服务器有位置信息,部分没有。验证了优先选择有位置信息的服务器。


174-191: 服务器无效位置信息处理测试合理

正确测试了服务器位置信息无效时的容错处理。

discovery/seata-discovery-nacos/src/main/java/org/apache/seata/discovery/registry/nacos/NacosRegistryServiceImpl.java (7)

80-80: 字段重命名和类型升级合理

CLUSTER_ADDRESS_MAP 重命名为 CLUSTER_INSTANCE_MAP 并升级类型,更准确地反映了存储内容。


117-127: register 方法升级实现正确

正确地从 ServiceInstance 中提取地址信息,保持了原有注册逻辑。


130-140: unregister 方法升级实现正确

与 register 方法保持一致的处理方式。


172-191: SLB 模式下的 ServiceInstance 处理正确

正确地将公网 IP 和端口信息转换为 ServiceInstance,并保留了服务元数据。使用前缀区分 SLB 地址缓存是良好的设计。


199-229: 非 SLB 模式的实例转换和过滤逻辑正确

正确地将 Nacos Instance 列表转换为 ServiceInstance 列表,保留了原有的健康检查和启用状态过滤,同时保留了实例元数据。


26-26: 导入语句添加正确

添加了必要的 ServiceInstance 导入。


40-40: Collections 导入添加合理

用于 SLB 模式下创建单例列表。

discovery/seata-discovery-sofa/src/main/java/org/apache/seata/discovery/registry/sofa/SofaRegistryServiceImpl.java (4)

29-29: 类型升级和命名改进正确

ServiceInstance 导入和字段重命名符合整体架构升级。

Also applies to: 78-78


106-121: 注册和注销方法升级正确

正确处理 ServiceInstance 参数,保持了原有业务逻辑。


148-148: 方法签名保持正确

subscribe 和 unsubscribe 方法不需要修改,保持原有逻辑。

Also applies to: 158-158


163-190: lookup 方法升级实现正确

正确地将返回类型改为 ServiceInstance 列表,并在订阅回调中进行适当的数据转换。

discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplMockTest.java (5)

64-91: 测试设置和清理逻辑完善

正确使用反射清理静态状态,确保测试间的隔离性。


99-118: 注册测试实现正确

正确使用静态 mock 测试注册流程,验证了关键方法调用。


187-209: 订阅和取消订阅测试完善

正确验证了监听器的管理逻辑。


241-252: 命名空间测试实现正确

正确测试了从系统属性获取命名空间的功能,并适当清理了系统属性。


254-276: 配置相关测试实现合理

正确测试了配置键和服务组的获取逻辑。

seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/client/RoutingProperties.java (2)

27-44: 配置类定义和基本属性设置合理

使用常量引用配置前缀,默认值设置合理(路由功能默认关闭)。


87-202: 流式 API 设计优秀

所有 setter 方法返回 this 支持链式调用,辅助方法提供了便捷的元数据路由器管理。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/DefaultRouterChain.java (4)

37-52: 类结构设计合理

使用责任链模式封装多个路由器的实现很恰当,通过 RoutingProperties 集中管理配置也符合最佳实践。


73-82: 过滤方法实现高效

使用 BitList 作为中间数据结构进行过滤操作的设计很好,可以提高处理效率。


159-175: 路由器加载逻辑清晰

按配置顺序加载路由器并构建责任链的实现很好,代码结构清晰易懂。


246-285: 配置解析逻辑健壮

路由器顺序解析方法实现良好,具有完善的验证逻辑和合理的降级策略。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/registry/RegistryService.java (3)

33-63: 接口重构设计合理

将原始的 InetSocketAddress 迁移到 ServiceInstance 抽象是一个很好的设计决策,为未来的元数据扩展提供了更好的支持。


65-111: 方法签名更新一致

所有方法签名都已正确更新为使用 ServiceInstance,保持了接口的一致性。


127-189: 默认方法实现正确

所有默认方法都已正确更新以使用 ServiceInstance,流操作和集合处理逻辑保持不变。

discovery/seata-discovery-zk/src/main/java/org/apache/seata/discovery/registry/zk/ZookeeperRegisterServiceImpl.java (4)

85-96: 字段重命名和类型更新恰当

CLUSTER_ADDRESS_MAP 重命名为 CLUSTER_INSTANCE_MAP 并更新类型为 List<ServiceInstance> 更准确地反映了其用途。


111-157: 注册/注销方法适配良好

方法签名更新为接收 ServiceInstance 参数,同时保持内部逻辑不变,通过 instance.getAddress() 提取地址信息的方式很合理。


213-249: 查找方法返回类型更新正确

lookupdoLookup 方法都已正确更新为返回 List<ServiceInstance>,与整体设计保持一致。


356-374: 实例映射刷新逻辑正确

从路径字符串解析并创建 ServiceInstance 对象的实现合理,错误处理也很恰当。

discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java (3)

106-124: 静态字段类型更新一致

INIT_ADDRESSESALIVE_NODES 都已正确更新为使用 ServiceInstance,与整体重构保持一致。


406-483: 服务实例查找和刷新逻辑正确

aliveLookuprefreshAliveLookup 方法已正确适配 ServiceInstance,流式处理和过滤逻辑保持不变。


579-619: 查找方法实现完善

从配置初始化 ServiceInstance 对象以及从 Node 列表转换的实现都很合理,错误处理也很完善。

core/src/test/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClientTest.java (2)

53-124: 测试类结构设计良好

测试类使用 Mockito 进行模拟,正确地扩展了 AbstractNettyRemotingClient 并在 tearDown 方法中清理系统属性,确保了测试隔离性。


484-501: 辅助方法实现清晰

createServiceInstances 辅助方法使用 lenient stubbing 创建模拟对象的方式很合适,使测试代码更简洁易读。

discovery/seata-discovery-namingserver/src/test/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImplTest.java (6)

54-91: 设置方法实现良好

测试设置全面,正确配置了全局实例、系统属性和 Spring 环境。将 metadataMaxAgeMs 设置为较小值(1000ms)有助于加快测试执行。


93-101: 清理方法实现正确

正确清理了所有在 beforeClass 中设置的系统属性,确保了测试隔离性。


103-110: 测试实现正确

通过反射测试私有方法 getNamingAddrs 的实现是合理的,断言检查符合预期。


112-120: 禁用的测试需要本地 namingserver

该测试被标记为 @Disabled,需要本地启动 namingserver 才能运行。测试实现本身看起来是正确的。


143-162: 元数据处理测试实现良好

测试正确验证了注册时的元数据处理,包括嵌套的元数据结构。测试覆盖全面。


210-242: 测试和辅助方法实现良好

testAliveLookup 测试简单有效。reflectUnsubscribe 辅助方法和内部监听器类实现正确。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/config/RoutingProperties.java (2)

24-76: 配置常量定义规范

配置键常量定义清晰,命名规范统一,注释完整。很好地集中管理了路由相关的配置项。


173-209: 动态元数据路由器配置实现巧妙

支持单个 metadata-router 和多个编号的 metadata-router(如 metadata-router-1、metadata-router-2)的设计很灵活,实现正确。

discovery/seata-discovery-namingserver/src/main/java/org/apache/seata/discovery/registry/namingserver/NamingserverRegistryServiceImpl.java (4)

78-152: 类结构和初始化实现良好

单例模式实现正确,健康检查机制设计合理,使用定时任务定期检查 naming server 的可用性。


154-188: 健康检查实现健壮

健康检查逻辑完善,包含了阈值判断、状态记录和日志输出。HTTP 健康检查端点使用正确。


274-315: 订阅机制实现完善,但需注意线程管理

订阅实现同时支持推拉模式,逻辑完整。但要注意 NOTIFIER_EXECUTOR 中的线程在 isSubscribed 为 false 时才会退出,确保在适当时机设置该标志。


543-569: 命名服务器地址选择实现优秀

getNamingAddr 方法实现了带健康检查的负载均衡,使用缓存提高性能,随机选择保证负载分散。实现非常完善。

discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/loadbalance/LoadBalanceTest.java (3)

42-172: 现有测试重构完成度高

所有负载均衡测试都已正确迁移到使用 ServiceInstance,保持了原有的测试逻辑和覆盖率。参数化测试使用得当。


174-219: 加权负载均衡测试设计良好

新增的测试很好地覆盖了加权负载均衡的两种场景:

  1. 无权重时降级为随机负载均衡
  2. 有权重时按权重分配

容差设置合理(20%-30%),适合随机分布的验证。


327-347: 权重提取方法实现健壮

getWeightFromInstance 方法很好地处理了多种情况:

  • 支持 Number 和 String 类型的权重值
  • 有适当的异常处理
  • 确保返回非负值

实现考虑周全。

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (6)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (3)

33-40: 字段应声明为 private 以提高封装性

字段应该声明为 private,并且构造函数应该对 metadata 进行防御性复制,避免外部修改影响内部状态。


42-46: 构造函数缺少空值检查

Instance 创建 ServiceInstance 时应该添加对输入参数及其嵌套属性的空值检查,防止运行时出现 NullPointerException


56-66: 建议移除 setter 方法以保证不可变性

ServiceInstance 作为值对象应该是不可变的。建议移除 setter 方法,如需修改应创建新实例或使用 Builder 模式。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/WeightedRandomLoadBalance.java (1)

44-49: 改进泛型类型安全性

当前实现使用 instanceof ServiceInstance 检查,但对于泛型类型 <T> 不够安全。如果调用者传入非 ServiceInstance 类型的对象,可能导致意外行为。建议在方法开始时验证所有元素类型。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java (2)

39-39: 线程安全问题:expression 字段的并发访问

虽然 expression 字段声明为 volatile 并在 doRoute 中创建了本地副本,但这仍不能完全解决并发问题。建议使用 AtomicReference 或其他线程安全机制。

Also applies to: 61-61, 85-87


69-69: 性能优化:避免重复解析表达式

每次调用 doRoute 方法时都会重新解析表达式,这在高并发场景下可能成为性能瓶颈。建议缓存解析结果。

🧹 Nitpick comments (3)
common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1)

73-82: 建议使用 Stream API 简化实现

可以使用 Stream API 来简化这两个转换方法的实现,使代码更简洁易读。

-    public static List<ServiceInstance> convertToServiceInstanceList(List<InetSocketAddress> addresses) {
-        List<ServiceInstance> serviceInstances = new ArrayList<>();
-        if (addresses != null && !addresses.isEmpty()) {
-            for (InetSocketAddress address : addresses) {
-                NetUtil.validAddress(address);
-                serviceInstances.add(new ServiceInstance(address, null));
-            }
-        }
-        return serviceInstances;
-    }
+    public static List<ServiceInstance> convertToServiceInstanceList(List<InetSocketAddress> addresses) {
+        if (addresses == null || addresses.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return addresses.stream()
+            .peek(NetUtil::validAddress)
+            .map(addr -> new ServiceInstance(addr, null))
+            .collect(Collectors.toList());
+    }

Also applies to: 89-98

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java (1)

76-78: 单表达式逻辑的注释令人困惑

第 76 行的注释提到"虽然只有一个条件",但仍使用 allMatch。如果确实只有一个条件,anyMatchallMatch 的结果应该相同。建议要么支持多条件的 AND 逻辑,要么简化代码逻辑。

discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/DefaultRouterChain.java (1)

73-82: 考虑优化 BitList 转换以提升性能

当前实现在 filterAll 方法中进行了 List -> BitList -> List 的转换。如果调用方频繁调用此方法,这些转换可能会影响性能。建议考虑:

  1. 提供一个直接接受和返回 BitList 的公共方法,让调用方根据需要选择使用
  2. 或者在上层缓存 BitList 格式的数据,避免重复转换
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 90eb1cb and d05e99a.

📒 Files selected for processing (21)
  • common/src/main/java/org/apache/seata/common/metadata/ServiceInstance.java (1 hunks)
  • common/src/test/java/org/apache/seata/common/metadata/ServiceInstanceTest.java (1 hunks)
  • core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClient.java (4 hunks)
  • discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java (7 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/WeightedRandomLoadBalance.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingManager.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/DefaultRouterChain.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/PrimaryBackupRouterChain.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcher.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ExpressionParser.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/GeoLocation.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/MetadataRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/MetadataRouterTest.java (1 hunks)
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/RegionRouterTest.java (1 hunks)
  • discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java (10 hunks)
  • discovery/seata-discovery-eureka/src/main/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java (7 hunks)
  • discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java (12 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfigTest.java (1 hunks)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (15)
  • seata-spring-autoconfigure/seata-spring-autoconfigure-client/src/test/java/org/apache/seata/spring/boot/autoconfigure/properties/client/MetadataRouterConfigTest.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/region/GeoLocation.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/PrimaryBackupRouterChain.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/BitList.java
  • discovery/seata-discovery-consul/src/main/java/org/apache/seata/discovery/registry/consul/ConsulRegistryServiceImpl.java
  • core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingClient.java
  • seata-spring-autoconfigure/seata-spring-autoconfigure-core/src/main/java/org/apache/seata/spring/boot/autoconfigure/properties/registry/RegistryMetadataProperties.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ConfigurableConditionMatcher.java
  • common/src/test/java/org/apache/seata/common/metadata/ServiceInstanceTest.java
  • discovery/seata-discovery-etcd3/src/main/java/org/apache/seata/discovery/registry/etcd3/EtcdRegistryServiceImpl.java
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/RegionRouterTest.java
  • discovery/seata-discovery-eureka/src/main/java/org/apache/seata/discovery/registry/eureka/EurekaRegistryServiceImpl.java
  • discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/RoutingManager.java
  • discovery/seata-discovery-core/src/test/java/org/apache/seata/discovery/routing/router/MetadataRouterTest.java
  • discovery/seata-discovery-raft/src/main/java/org/apache/seata/discovery/registry/raft/RaftRegistryServiceImpl.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: build (8)
  • GitHub Check: build (21)
  • GitHub Check: build (17)
  • GitHub Check: Analyze (java)
🔇 Additional comments (2)
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/loadbalance/WeightedRandomLoadBalance.java (1)

74-75: 权重选择逻辑的兜底处理需要审查

第 74 行返回 invokers.get(0) 作为兜底逻辑在理论上不应该被执行到。如果执行到这里,说明权重选择逻辑可能存在问题。建议添加日志记录或抛出异常来帮助调试。

-        return invokers.get(0);
+        // This should never happen if weight calculation is correct
+        throw new IllegalStateException("Weight selection failed, this indicates a bug in weight calculation");
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/chain/DefaultRouterChain.java (1)

270-270: 缺少 RouterChainUtils 的导入语句

代码中使用了 RouterChainUtils.isValidRouterName(routerName) 方法,但文件头部没有相应的 import 语句。

请在文件头部添加必要的导入:

+import org.apache.seata.discovery.routing.chain.RouterChainUtils;

Likely an incorrect or invalid review comment.

Comment on lines +165 to +168
String[] parts = cleanExpression.split("\\s+");
if (parts.length != 3) {
return false;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

表达式验证对包含空格的值处理不当

当前的验证逻辑通过空格分割表达式并期望恰好 3 个部分,这对于值中包含空格的情况(如 city = "New York")会导致验证失败。建议使用更智能的解析方式,例如正则表达式来正确处理带引号的值。

-        String[] parts = cleanExpression.split("\\s+");
-        if (parts.length != 3) {
-            return false;
-        }
+        // Use regex to properly parse expression with potential spaces in values
+        Pattern pattern = Pattern.compile("^(\\S+)\\s+(=|!=|>|>=|<|<=)\\s+(.+)$");
+        Matcher matcher = pattern.matcher(cleanExpression);
+        if (!matcher.matches()) {
+            return false;
+        }
+        String key = matcher.group(1);
+        String operator = matcher.group(2);
+        String value = matcher.group(3);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
String[] parts = cleanExpression.split("\\s+");
if (parts.length != 3) {
return false;
}
// Use regex to properly parse expression with potential spaces in values
Pattern pattern = Pattern.compile("^(\\S+)\\s+(=|!=|>|>=|<|<=)\\s+(.+)$");
Matcher matcher = pattern.matcher(cleanExpression);
if (!matcher.matches()) {
return false;
}
String key = matcher.group(1);
String operator = matcher.group(2);
String value = matcher.group(3);
🤖 Prompt for AI Agents
In
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/expression/ExpressionParser.java
around lines 165 to 168, the current expression validation splits the input by
whitespace expecting exactly three parts, which fails for values containing
spaces like city = "New York". To fix this, replace the simple split with a
regex-based parser that correctly handles quoted strings, ensuring the entire
quoted value is treated as a single part during validation.

Comment on lines +47 to +48
this.regionTopN = RoutingProperties.getRegionRouterTopN();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

需要验证 regionTopN 参数的有效性

regionTopN 参数没有进行有效性检查。如果配置值为 0 或负数,会导致返回空列表,这可能不是期望的行为。建议添加参数验证。

     public RegionRouter() {
         super("RegionRouter", true);
         this.regionTopN = RoutingProperties.getRegionRouterTopN();
+        if (this.regionTopN <= 0) {
+            throw new IllegalArgumentException("regionTopN must be positive, got: " + this.regionTopN);
+        }
     }

Also applies to: 65-66

🤖 Prompt for AI Agents
In
discovery/seata-discovery-core/src/main/java/org/apache/seata/discovery/routing/router/RegionRouter.java
around lines 47-48 and 65-66, the regionTopN parameter is assigned without
validation, which can cause unexpected behavior if it is zero or negative. Add
validation checks after retrieving regionTopN to ensure it is a positive
integer; if not, set a default positive value or throw an appropriate exception
to prevent returning empty lists unintentionally.

@YoWuwuuuw YoWuwuuuw changed the title Gsoc routing support mock CR: Gsoc routing support mock Aug 23, 2025
@YoWuwuuuw YoWuwuuuw changed the title CR: Gsoc routing support mock CR: Gsoc routing support Aug 23, 2025
@YoWuwuuuw YoWuwuuuw closed this Oct 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants