doc:文档更新
This commit is contained in:
158
doc/中铜技术文档/Seata分布式事务集成参考.md
Normal file
158
doc/中铜技术文档/Seata分布式事务集成参考.md
Normal file
@@ -0,0 +1,158 @@
|
||||
[Seata分布式事务集成参考.md](Seata%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E9%9B%86%E6%88%90%E5%8F%82%E8%80%83.md)# Seata 分布式事务集成参考
|
||||
|
||||
## 一、架构说明
|
||||
|
||||
### 多环境 Seata 配置管理
|
||||
|
||||
所有环境的 Seata 配置统一通过 Nacos 管理,本地配置文件不包含 Seata 配置。
|
||||
|
||||
```
|
||||
├── dev 环境: base-server-dev.yaml (dev_tx_group, namespace: dev)
|
||||
├── test 环境: base-server-test.yaml (test_tx_group, namespace: test)
|
||||
└── prod 环境: base-server-prod.yaml (prod_tx_group, namespace: prod)
|
||||
|
||||
Seata Server: 172.16.46.63:30088
|
||||
```
|
||||
|
||||
### 为什么使用 IP 直连?
|
||||
|
||||
Nacos 的 namespace 隔离机制导致不同命名空间的应用无法跨 namespace 发现服务。Seata Server 通过 IP 直连(`registry.type=file`)避免此限制,所有环境共享同一个 Seata Server,通过不同的 `tx-service-group` 实现逻辑隔离。
|
||||
|
||||
---
|
||||
|
||||
## 二、Nacos 配置
|
||||
|
||||
在对应环境的 Nacos 配置中心创建配置文件。以 `base-server-dev.yaml` 为例(其他环境只需修改 `tx-service-group`):
|
||||
|
||||
```yaml
|
||||
seata:
|
||||
enabled: true
|
||||
application-id: base-server
|
||||
tx-service-group: dev_tx_group
|
||||
enable-auto-data-source-proxy: true
|
||||
data-source-proxy-mode: AT
|
||||
registry:
|
||||
type: file
|
||||
config:
|
||||
type: file
|
||||
service:
|
||||
vgroupMapping:
|
||||
default_tx_group: default
|
||||
dev_tx_group: default
|
||||
test_tx_group: default
|
||||
prod_tx_group: default
|
||||
default:
|
||||
grouplist: 172.16.46.63:30088
|
||||
client:
|
||||
tm:
|
||||
defaultGlobalTransactionTimeout: 60000
|
||||
undo:
|
||||
logTable: undo_log
|
||||
dataValidation: true
|
||||
logSerialization: jackson
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、业务集成步骤
|
||||
|
||||
### 步骤 1:在 pom.xml 中添加依赖
|
||||
|
||||
Seata 2.4.0 版本已在 `zt-dependencies` 中统一管理。业务模块只需在 `pom.xml` 中添加:
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
版本号会从 `zt-dependencies` 继承。
|
||||
|
||||
### 步骤 2:创建 undo_log 表
|
||||
|
||||
在业务数据库执行:
|
||||
|
||||
```sql
|
||||
CREATE TABLE "UNDO_LOG" (
|
||||
"BRANCH_ID" BIGINT NOT NULL,
|
||||
"XID" VARCHAR(128) NOT NULL,
|
||||
"CONTEXT" VARCHAR(128) NOT NULL,
|
||||
"ROLLBACK_INFO" BLOB NOT NULL,
|
||||
"LOG_STATUS" INT NOT NULL,
|
||||
"LOG_CREATED" DATETIME DEFAULT SYSDATE,
|
||||
"LOG_MODIFIED" DATETIME DEFAULT SYSDATE,
|
||||
PRIMARY KEY ("BRANCH_ID")
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "UX_UNDO_LOG" ON "UNDO_LOG" ("XID", "BRANCH_ID");
|
||||
```
|
||||
|
||||
### 步骤 3:在 Service 方法上添加 @GlobalTransactional 注解
|
||||
|
||||
```java
|
||||
import io.seata.spring.annotation.GlobalTransactional;
|
||||
|
||||
@Service
|
||||
public class OrderServiceImpl implements OrderService {
|
||||
|
||||
@GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Long createOrder(OrderCreateReqVO req) {
|
||||
// 本地操作
|
||||
orderMapper.insert(order);
|
||||
|
||||
// 跨服务调用自动参与分布式事务
|
||||
inventoryApi.deduct(productId, quantity);
|
||||
|
||||
return order.getId();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**说明**:
|
||||
- 只在事务发起方添加注解
|
||||
- 被调用的其他服务自动参与,无需额外配置
|
||||
- Seata 自动通过 HTTP Header 传递事务 ID
|
||||
|
||||
---
|
||||
|
||||
## 四、配置汇总
|
||||
|
||||
| 配置项 | 开发环境 | 测试环境 | 生产环境 |
|
||||
|--------|---------|---------|---------|
|
||||
| **tx-service-group** | `dev_tx_group` | `test_tx_group` | `prod_tx_group` |
|
||||
| **Nacos 命名空间** | `hwc` | `test` | `prod` |
|
||||
| **Seata Server** | `172.16.46.63:30088` | `172.16.46.63:30088` | `172.16.46.63:30088` |
|
||||
|
||||
---
|
||||
|
||||
## 五、其他事务模式
|
||||
|
||||
当前配置默认使用 **AT 模式**(自动事务模式)。Seata 还支持其他事务模式,需要业务自己实现:
|
||||
|
||||
### TCC 模式
|
||||
|
||||
需要实现 Try、Confirm、Cancel 三个业务方法,使用 `@TwoPhaseBusinessAction` 注解标记。详见官方文档。
|
||||
|
||||
### Saga 模式
|
||||
|
||||
需要定义 Saga 流程和状态机。详见官方文档。
|
||||
|
||||
### XA 模式
|
||||
|
||||
需要数据库支持 XA 事务,配置中修改 `data-source-proxy-mode: XA`。
|
||||
|
||||
**详见**: https://seata.apache.org/zh-cn/docs/overview/what-is-seata
|
||||
|
||||
---
|
||||
|
||||
## 六、Seata 控制台
|
||||
|
||||
**地址**: `http://172.16.46.63:30087`
|
||||
|
||||
可查看全局事务、分支事务、全局锁等监控信息。
|
||||
|
||||
---
|
||||
|
||||
**官方文档**: https://seata.apache.org/zh-cn/docs/overview/what-is-seata
|
||||
212
doc/中铜技术文档/计量单位转换使用文档.md
Normal file
212
doc/中铜技术文档/计量单位转换使用文档.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 计量单位转换业务使用文档
|
||||
|
||||
## 一、系统概述
|
||||
|
||||
计量单位转换提供统一的计量单位转换服务,支持同一量纲内的单位自动转换。采用**单向配置、双向生效**机制,只需配置"非基准单位 → 基准单位"的转换规则,自动推导反向和间接转换。
|
||||
|
||||
**核心特性**:
|
||||
- 单向配置、双向生效的转换机制
|
||||
- 支持按单位ID、符号、名称进行转换
|
||||
- 高精度计算,支持批量操作
|
||||
- 跨模块统一服务
|
||||
|
||||
## 二、内容配置
|
||||
|
||||
### 2.1 管理菜单路径
|
||||
后台管理 → 基础管理 → 计量单位 → 计量单位管理
|
||||
|
||||
### 2.2 配置功能
|
||||
|
||||
#### 计量量纲管理
|
||||
- **功能**:创建和管理不同的量纲类型(如重量、长度、体积等)
|
||||
- **操作**:新增量纲、编辑量纲信息、删除量纲
|
||||
- **每个量纲只能设置一个基准单位**
|
||||
|
||||
#### 计量单位管理
|
||||
- **功能**:创建和管理具体的计量单位
|
||||
- **操作**:新增单位、编辑单位信息、删除单位
|
||||
- **关联量纲**:将单位归属到具体的量纲下
|
||||
|
||||
#### 转换规则配置
|
||||
- **功能**:配置单位间的转换规则
|
||||
- **配置原则**:只需配置"非基准单位 → 基准单位"
|
||||
- **自动推导**:系统自动推导反向转换和间接转换
|
||||
|
||||
### 2.3 配置建议
|
||||
|
||||
1. **量纲规划**:提前规划好业务需要的量纲类型
|
||||
2. **基准单位选择**:选择业务中最常用、最稳定的单位作为基准
|
||||
3. **转换规则**:优先使用整数转换系数,提高计算精度
|
||||
4. **定期校验**:使用转换路径校验功能确保配置正确性
|
||||
5. **转换完整性校验**:系统提供同一量纲内所有单位能否互相转换的校验功能,确保转换配置的完整性
|
||||
|
||||
## 三、API接口清单
|
||||
|
||||
### 3.1 单位管理接口
|
||||
|
||||
| 接口 | 方法 | 路径 | 说明 | API文档 |
|
||||
|------|------|------|------|---------|
|
||||
| 获取量纲树 | GET | `/admin-api/base/unit-management/unit-quantity/tree` | 获取量纲和单位树形结构 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E8%AE%A1%E9%87%8F%E5%8D%95%E4%BD%8D%E9%87%8F/getUnitQuantityTree) |
|
||||
| 获取单位列表 | GET | `/admin-api/base/unit-management/unt-info/page` | 获取单位列表(用于下拉选择) | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E8%AE%A1%E9%87%8F%E5%8D%95%E4%BD%8D/getUntInfoPage) |
|
||||
|
||||
### 3.2 单位转换接口
|
||||
|
||||
| 接口 | 方法 | 路径 | 说明 | API文档 |
|
||||
|------|------|------|------|---------|
|
||||
| 按ID转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert` | 通过单位ID转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convert) |
|
||||
| 按符号转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert-by-symbol` | 通过单位符号转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convertBySymbol) |
|
||||
| 按名称转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert-by-name` | 通过单位名称转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convertByName) |
|
||||
| 批量ID转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert` | 按ID批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvert) |
|
||||
| 批量符号转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert-by-symbol` | 按符号批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvertBySymbol) |
|
||||
| 批量名称转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert-by-name` | 按名称批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvertByName) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 三、后端业务调用示例
|
||||
|
||||
### base模块内使用
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class PurchaseOrderServiceImpl {
|
||||
|
||||
@Resource
|
||||
private UnitConversionService unitConversionService;
|
||||
|
||||
/**
|
||||
* 处理采购订单,统一转换为千克计算
|
||||
*/
|
||||
public void processPurchaseOrder(PurchaseOrderSaveReqVO orderVO) {
|
||||
for (PurchaseOrderDetailVO detail : orderVO.getDetails()) {
|
||||
// 方式1:按符号转换
|
||||
UnitConvertBySymbolReqVO convertReq = new UnitConvertBySymbolReqVO();
|
||||
convertReq.setSrcUnitSymbol(detail.getUnt());
|
||||
convertReq.setTgtUnitSymbol("kg");
|
||||
convertReq.setValue(detail.getQty());
|
||||
convertReq.setPrecision(6);
|
||||
|
||||
UnitConvertRespVO result = unitConversionService.convertBySymbol(convertReq);
|
||||
BigDecimal standardQuantity = result.getConvertedValue();
|
||||
|
||||
// 方式2:按ID转换(如果有单位ID)
|
||||
// UnitConvertReqVO convertReq = new UnitConvertReqVO();
|
||||
// convertReq.setSrcUntId(detail.getUntId());
|
||||
// convertReq.setTgtUntId(kgUnitId);
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 四、跨模块调用
|
||||
|
||||
### 4.1 直接Service调用(推荐)
|
||||
|
||||
在同一服务内直接注入使用:
|
||||
```java
|
||||
@Resource
|
||||
private UnitConversionService unitConversionService;
|
||||
```
|
||||
|
||||
### 4.2 跨服务调用(按需使用)
|
||||
|
||||
**1. 在 API 模块中定义 Feign 接口:**
|
||||
|
||||
```java
|
||||
package com.zt.plat.module.base.api;
|
||||
|
||||
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||
import com.zt.plat.module.base.enums.ApiConstants;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@FeignClient(name = ApiConstants.NAME)
|
||||
@Tag(name = "RPC 服务 - 单位转换")
|
||||
public interface UnitConversionApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/unit-conversion";
|
||||
|
||||
@PostMapping(PREFIX + "/convert")
|
||||
@Operation(summary = "按ID转换单位")
|
||||
CommonResult<UnitConvertRespVO> convert(@RequestBody UnitConvertReqVO reqVO);
|
||||
|
||||
@PostMapping(PREFIX + "/convert-by-symbol")
|
||||
@Operation(summary = "按符号转换单位")
|
||||
CommonResult<UnitConvertRespVO> convertBySymbol(@RequestBody UnitConvertBySymbolReqVO reqVO);
|
||||
}
|
||||
```
|
||||
|
||||
**2. 在其他服务中调用:**
|
||||
|
||||
```java
|
||||
@Service
|
||||
public class PurchaseServiceImpl {
|
||||
|
||||
@Resource
|
||||
private UnitConversionApi unitConversionApi;
|
||||
|
||||
public void processPurchase(PurchaseVO purchase) {
|
||||
UnitConvertBySymbolReqVO convertReq = new UnitConvertBySymbolReqVO();
|
||||
convertReq.setSrcUnitSymbol(purchase.getUnit());
|
||||
convertReq.setTgtUnitSymbol("kg");
|
||||
convertReq.setValue(purchase.getQuantity());
|
||||
convertReq.setPrecision(6);
|
||||
|
||||
CommonResult<UnitConvertRespVO> result = unitConversionApi.convertBySymbol(convertReq);
|
||||
if (result.isSuccess()) {
|
||||
BigDecimal standardQty = result.getData().getConvertedValue();
|
||||
// 业务处理
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、前端使用
|
||||
|
||||
### 5.1 基本API调用
|
||||
|
||||
```typescript
|
||||
// 获取量纲树
|
||||
export const getUnitQuantityTree = () => {
|
||||
return request.get('/admin-api/base/unit-management/unit-quantity/tree')
|
||||
}
|
||||
|
||||
// 获取单位列表
|
||||
export const getUntInfoPage = (params: any) => {
|
||||
return request.get('/admin-api/base/unit-management/unt-info/page', { params })
|
||||
}
|
||||
|
||||
// 单位转换
|
||||
export const convertUnitBySymbol = (data: any) => {
|
||||
return request.post('/admin-api/base/unit-management/unit-conversion/convert-by-symbol', data)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 六、常见问题
|
||||
|
||||
**Q1: 前端如何获取单位选项?**
|
||||
|
||||
A: 使用 `/admin-api/base/unit-management/unit-quantity/tree` 获取量纲树,然后根据选择的量纲调用 `/admin-api/base/unit-management/unt-info/page` 获取单位列表。
|
||||
|
||||
**Q2: 按ID转换和按符号转换哪个更好?**
|
||||
|
||||
A: 按ID转换更稳定,因为数据库ID不会变化。建议在前端保存单位ID,在业务转换时使用ID调用。
|
||||
|
||||
**Q3: 跨服务调用需要特殊配置吗?**
|
||||
|
||||
A: 不需要,项目已经统一配置好。所有Feign客户端都使用 `name = "base-server"`,路径使用 `/rpc-api` 前缀。
|
||||
|
||||
**Q4: 批量转换性能问题?**
|
||||
|
||||
A: 使用批量接口,设置ignoreErrors=true。
|
||||
|
||||
Reference in New Issue
Block a user