YoWuwuuuw opened a new issue, #7547:
URL: https://github.com/apache/incubator-seata/issues/7547

   ### Check Ahead
   
   - [x] I have searched the [issues](https://github.com/seata/seata/issues) of 
this repository and believe that this is not a duplicate.
   
   - [x] I am willing to try to implement this feature myself.
   
   
   ### Why you need it?
   
   To enhance Apache Seata's routing intelligence and flexibility in 
multi-node, cross-region, and multi-environment deployments, this proposal 
designs and implements:
   
   - A pluggable routing filter mechanism based on the Chain of Responsibility 
pattern;
   
   - **Expression-based routing configuration** using service metadata such as 
region, env, version, etc.;
   
   - Support for **configuration-driven**, **dynamically extensible**, and 
**hot-pluggable** router modules;
   
   - Features such as **primary-backup routing**, **snapshot debugging**, and 
**performance optimizations like `BitList`**.
   
   ### How it could be?
   
   #### 1. Core Routing Flow
   Request routing flow:
   ```
   Client Request
      ↓
   Service instance discovery from registry (with metadata)
      ↓
   RouterChain execution:
      - RegionRouter (geolocation)
      - MetadataMatchRouter (version, environment, etc.)
      - Custom routers (via SPI)
      ↓
   Filtered candidate Server list
      ↓
   Load Balance selects the final Server
      ↓
   Request sent to selected Server
   ```
   
   #### 2. Supported Routing Filter Types
   | Router Type         | Description                            | Metadata 
Field(s) | Notes                                                                
                      |
   
|---------------------|------------------------------------|-------------------|--------------------------------------------------------------------------------------------|
   | RegionRouter        | Matches geographic region or distance | region       
     | Geo-aware filtering: **calculates distance** from client via coordinates 
and selects the nearest N Server instances (e.g., regionTopN = 5) to achieve 
optimal latency. |
   | MetadataMatchRouter | Matches arbitrary metadata expressions | version, 
env      | General-purpose string match with support for **logical 
expressions** ("AND", "OR") and **conditional operators** (e.g., >=, <=, <, >). 
|
   | xxxRouter           | Custom rule via SPI                   | —            
     | User-implemented filters via **SPI**. Only sequence-based, not 
combinable with expression-based routers. |
   
   
   
   
   #### 3. Routing Rule Configuration (YAML)
   ```
   registry:
     route:
       enabled: true
       chain:
         - RegionRouter
         - MetadataRouter
       RegionRouter:
         enabled: true
         regionTopN: 5
       MetadataRouter:
         expression: "version >= 2.3 | env = dev"
       fallbackToAny: true
       snapshot-log:
         enabled: true
   ```
   
   
   #### 4. Fallback Mechanism
   > To ensure high availability, the routing filter chain supports a fallback 
mechanism.
   
   Scenarios:
   
   - When any router (e.g., RegionRouter or MetadataRouter) filters out all 
service instances;
   
   - To prevent transaction failures or unavailability, fallback is triggered;
   
   - The system reverts to using the full list of available Seata Server 
instances for downstream routing and load balancing.
   
   Example:
   `registry.route.fallbackToAny: true`
   
   
   #### 5. Future Extensibility
   
   - Hot-reload of routing expressions with visual UI editor
   
   - Dynamic lifecycle management of filter chain (add/remove/disable routers 
at runtime)
   
   ### Other related information
   
   #### Module Design
   ##### 1. StateRouter<T> Interface
   ```
   public interface StateRouter<T> {
       BitList<T> route(BitList<T> servers,
                        RoutingContext ctx,
                        boolean debugMode,
                        Holder<RouterSnapshotNode<T>> snapshotHolder);
   
       boolean isRuntime();
       boolean isForce();
       String buildSnapshot();
       void setNext(StateRouter<T> next); // chain-of-responsibility
   }
   ```
   
   ##### 2. RegionRouter<T> – Geographic Distance Filter
   
   > Filters server instances based on the geographic distance from the client 
(from metadata coordinates), selecting the top-N closest instances.
   
   
   ```
   public class RegionRouter<T extends ServerInstance> extends 
AbstractStateRouter<T> {
   
       private final int regionTopN;
   
       @Override
       protected BitList<T> doRoute(BitList<T> servers, RoutingContext ctx) {
           GeoLocation clientLocation = getClientLocation(ctx);
   
           List<ServerWithDistance<T>> sorted = servers.stream()
               .map(s -> new ServerWithDistance<>(s, 
calculateDistance(clientLocation, s)))
               
.sorted(Comparator.comparingDouble(ServerWithDistance::getDistance))
               .limit(regionTopN)
               .collect(Collectors.toList());
   
           return BitList.fromList(sorted.stream()
               .map(ServerWithDistance::getServer)
               .collect(Collectors.toList()));
       }
   }
   ```
   
   ##### 3. MetadataRouter<T> – Metadata Expression Matcher
   
   > Supports advanced expression-based filtering (e.g., version >= 2.0 & env = 
dev).
   
   
   ```
   public class MetadataRouter<T extends ServerInstance> extends 
AbstractStateRouter<T> {
   
       private volatile String expression;
   
       @Override
       protected BitList<T> doRoute(BitList<T> servers, RoutingContext ctx) {
           List<ConditionMatcher> matchers = ExpressionParser.parse(expression);
           return servers.filter(server -> matchers.stream()
               .allMatch(m -> m.match(server, ctx)));
       }
   }
   ```
   
   ##### 4. RouterChain<T> – Filter Chain Controller
   
   > Implements the chain-of-responsibility routing pipeline, where each router 
processes and passes down a filtered BitList.
   
   
   ```
   class RoutingFilterChain {
       List<RoutingFilter> filters;
   
       BitList<Server> filterAll(BitList<Server> origin, MetadataContext ctx) {
           for (RoutingFilter f : filters) {
               origin = f.filter(origin, ctx);
           }
           return origin;
       }
   }
   ```
   
   ##### 5. ExpressionParser – Expression Engine
   Parses metadata-based filtering expressions. Expressions follow:
   - Exact match: key = value
   
   - Comparison operators: >=, <=, <, >
   
   - Logical operators: & (AND), | (OR)
   
   - Parentheses for precedence
   
   Example Expressions:
   version = 1.2 & env = dev
   region = cn-bj | region = cn-hz    // plain string matching, not geo-based
   version >= 2.0 | (env = staging & region != us-west)
   
   Features:
   
   - Case-sensitive matching
   
   - Optional fallback: If no match is found, fallback to all instances if 
fallback = true
   
   - Configurable router priorities or disable via enabled = false
   
   
   ##### 6. Primary-Backup Routing Chain
   
   > Supports active-failover between routing chains. Typically used in 
multi-region deployments, where a primary region is preferred, with automatic 
fallback to backup.
   
   ```
   public class PrimaryBackupRouterChain<T> {
   
       private volatile RouterChain<T> primaryChain;
       private volatile RouterChain<T> backupChain;
       private volatile RouterChain<T> current;
   
       public synchronized void updateServers(List<T> servers, Runnable 
onSwitch) {
           current = backupChain;
           primaryChain.setServers(servers);
           onSwitch.run();
           current = primaryChain;
           backupChain.setServers(servers);
       }
   }
   
   ```
   
   
   
   #### Optimization
   ##### 1. BitList<T> – High-Performance Filtering Structure
   A wrapper around BitSet to represent valid service candidates efficiently. 
Each filter updates only the active bitset, avoiding full array copies.
   ```
   BitList<ServerInstance> origin = new BitList<>(servers);
   BitList<ServerInstance> filtered = origin.filter(s -> s.region.equals("cn"));
   ```
   
    Text Diagram:
   ```
   Original list of service instances (indexed):
   Index:    0     1     2     3     4
   Servers:  A     B     C     D     E
   
   Initial BitSet (all 1s, meaning all valid):
   Bits:     1     1     1     1     1
   
   After RegionRouter filtering (keep only region = "cn"):
   Bits:     0     1     1     0     1
   Servers:        B     C           E
   
   After MetadataRouter filtering (keep only version >= 2.0):
   Bits:     0     1     0     0     1
   Servers:        B                 E
   ```
   
   ##### 2. SnapshotLogger – Router Debugging Output
   
   > Logs each routing step's filter results and decision-making process.
   
   Example Output:
   ```
   [RoutingChain] Service = 'default', Total servers = 5
   [RegionRouter] config: regionTopN = 3, matched = 3, selected = [192.168.1.1, 
192.168.1.3, 192.168.1.6]
   [MetadataMatchRouter] expression = "version >= 1.2 & env = dev", matched = 
2, selected = [192.168.1.3, 192.168.1.6]
   Final candidates: [192.168.1.3, 192.168.1.6]
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org
For additional commands, e-mail: notifications-h...@seata.apache.org

Reply via email to