YoWuwuuuw opened a new pull request, #7887:
URL: https://github.com/apache/incubator-seata/pull/7887

   <!--
       Licensed to the Apache Software Foundation (ASF) under one or more
       contributor license agreements.  See the NOTICE file distributed with
       this work for additional information regarding copyright ownership.
       The ASF licenses this file to You under the Apache License, Version 2.0
       (the "License"); you may not use this file except in compliance with
       the License.  You may obtain a copy of the License at
   
       http://www.apache.org/licenses/LICENSE-2.0
       
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
   -->
   <!-- Please make sure you have read and understood the contributing 
guidelines -->
   
   - [ ] I have read the 
[CONTRIBUTING.md](https://github.com/apache/incubator-seata/blob/2.x/CONTRIBUTING.md)
 guidelines.
   - [ ] I have registered the PR 
[changes](https://github.com/apache/incubator-seata/tree/2.x/changes).
   
   ### Ⅰ. Describe what this PR did
   #### 1. Core Capabilities and New Configuration Items
   
   ##### 1.1. Server Side: Metadata Registration
   
   + Seata-Server can **carry custom metadata** when registering with the 
registry center.
   
   ```properties
   
   # server: application.yaml, common metadata is provided, custom 
configuration items can be configured.
   
   # Common metadata for routing, custom metadata key-value pairs can be 
configured.
   
   seata.registry.metadata.weight: 1
   
   seata.registry.metadata.env:
   
   seata.registry.metadata.region:
   
   seata.registry.metadata.version:
   
   ```
   
   
   
   ##### 1.2. Client Side: Metadata-Driven Instance Selection
   
   Client instance selection is broken down into **two stages**: **route 
filtering and load balancing, the process is as follows**
   
   ```properties
   
   All Instances
   
   │
   ▼
   Metadata Routing (0 ~ N routers)
   
   │
   ▼
   Filtered Instances
   
   │
   ▼
   LoadBalance Strategy (random / round-robin / Advanced Load Balancing Based 
on Metadata
   
   │
   ▼
   Target Server Instance
   
   ```
   
   Configuration items are as follows:
   
   
   ```properties
   
   # Add load balancing strategy: Weighted Random
   
   seata.client.load-balance.type=WeightedRandomLoadBalance
   
   client.routing.enabled=false # Enable route filtering mode
   
   client.routing.debug=false # Debug mode, displaying detailed logs of the 
route filtering handler
   
   client.routing.routers= # Declare routers to load router configuration
   
   # 1. Single router: use metadata-router-1
   
   client.routing.routers = metadata-router-1
   
   client.routing.metadata-router-1.enabled = true
   
   client.routing.metadata-router-1.expression = version >= 2.3 && env == prod
   
   # 2. Multiple routers: use metadata-router-1, metadata-router-2, ...
   
   client.routing.routers = metadata-router-1, metadata-router-2, spi-cunstom
   
   client.routing.metadata-router-1.enabled = true
   
   client.routing.metadata-router-1.expression = version >= 2.0 || env == dev
   
   client.routing.metadata-router-2.enabled = true
   
   client.routing.metadata-router-2.expression = weight >= 1
   
   client.routing.spi-cunstom.enabled = true # Configurable SPI router, custom 
configuration and filtering logic, name must start with 'spi-'
   
   client.routing.spi-cunstom.xxx = ...
   
   ```
   
   
   
   
   #### 2. Expression Syntax:
   
   
   ##### 2.1. Basic Format
   
   `key operator value`, three parts separated by spaces: key name, operator, 
value
   
   
   
   
   ##### 2.2. Supported Operators
   
   | Operator        | Description      | Supported Types |
   |-----------------|------------------|-----------------|
   | == / =          | Equal to         | String, Number  |
   | !=              | Not equal to     | String, Number  |
   | > / >= / < / <= | Comparison       | Number only     |
   
   
   
   > <、>、>=、<= Only support numbers. If the instance metadata is not a number, 
it will return false and filter the instance.
   
   
   
   
   ##### 2.3. Expression Examples
   
   1. Single expression: `version >= 2.3`
   
   2. OR expression: `(version >= 2.3) || (env == dev)`
   
   3. AND expression: `(version >= 2.3) && (env == prod)`
   
   
   
   
   ##### 2.4. Expression Limitations
   
   Limitation: A single expression does not support mixing && and ||
   
   Solution: Use multiple || expressions in the router to implement complex 
logic
   
   ```properties
   
   # Implement the logic of (A || B) && (C || D)
   
   client.routing.metadata-router-1.expression= A || B
   client.routing.metadata-router-2.expression= C || D
   
   ```
   
   > Or use the distributive law: `(A && B) || (C && D) = (A || C) && (A || D) 
&& (B || C) && (B || D)`
   
   >
   
   
   #### 3. Metadata Enhancement for Each Registry
   
   
   
   ##### 3.1. Enhancement Methods
   
   | Registry        | Metadata Implementation                                  
 | Description |
   
|-----------------|-----------------------------------------------------------|-------------|
   | **Consul**      | Directly call the API's `setMeta()` / `getMeta()`        
  | Consul natively supports metadata fields, and the API handles them 
automatically |
   | **Nacos**       | Directly call the API's `setMetadata()` / 
`getMetadata()`  | Nacos natively supports metadata fields, and the API handles 
them automatically |
   | **Eureka**      | Through `instanceConfig.setMetadata()` / 
`instance.getMetadata()` | Eureka natively supports metadata 
fields;<br/>`getMetadataMap()` converts them to a `Map<String, String>` |
   | **Namingserver**| Based on the original API, metadata is part of the 
`Instance` object | The `Instance` object itself contains a `metadata` 
field,<br/>passed via JSON serialization/deserialization, which the API handles 
automatically |
   | **Zookeeper**   | Manually serialize metadata to string format 
(`key=value\n`) | Stored in the `data` of the `ZNode`, requiring manual 
serialization/deserialization |
   | **Redis**       | As shown below                                           
 | — |
   
   
   
   
   ##### 3.2. To be implemented
   
   | Registry | Status |
   |----------|--------|
   | **Etcd** | The original logic is not working; the existing implementation 
logic should be fixed first. |
   | **Sofa** | Cannot be built; a separate pull request will be made to 
enhance it in the future. |
   
   
   
   
   ##### 3.3. Redis Enhancement Description
   
   Implementation method: Manually build a hash structure to store metadata.
   
   Core design:
   
   + Maintain the original live keys. Unchanged: 
`registry.redis.${cluster}_${serverAddr}` (used for service discovery and 
heartbeat detection)
   
   + Added metadata key: `registry.redis.${cluster}.meta_${serverAddr}` (Hash 
structure, storing metadata)
   
   Backward compatibility:
   
   + When a new server registers, it creates both a liveness key and a metadata 
key (if metadata exists).
   
   + Existing clients only scan the liveness key and can discover new servers 
normally (ignoring the metadata key).
   
   + After scanning the liveness key, new clients attempt to retrieve the 
metadata key; if it does not exist or is empty, a ServiceInstance without 
metadata is created.
   
   Technical details:
   
   + Metadata is stored in a separate hash structure, decoupled from liveness 
detection.
   
   + The TTL of both keys is refreshed synchronously (5 seconds) to ensure data 
consistency.
   
   
   
   #### 4. Compatibility Notes
   
   + Enabling `routing` mode:
   
     - seata-server without metadata configuration:
     
       * When route filtering is enabled, instances without metadata will be 
filtered.
       
       * When using a weighted random load balancing strategy, a default weight 
of `weight=1` will be assigned.
     
     - seata-client does not enable `routing` mode: logical consistency 
backwards.
   
   
   
   ### Ⅱ. Does this pull request fix one issue?
   <!-- If that, add "fixes #xxx" below in the next line, for example, fixes 
#97. -->
   fixes #7886
   
   ### Ⅲ. Why don't you add test cases (unit test/integration test)? 
   
   
   ### Ⅳ. Describe how to verify it
   Refer to 
[#7550]([https://github.com/apache/incubator-seata/pull/7550](https://github.com/apache/incubator-seata/pull/7550)),
 use [demo](https://github.com/apache/incubator-seata/pull/7550), modify the 
corresponding configurations for verification.
   
   ### Ⅴ. Special notes for reviews
   
   


-- 
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: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to