580 lines
14 KiB
Markdown
580 lines
14 KiB
Markdown
# Task 服务新架构详细开发设计方案
|
||
|
||
## 1. 业务背景与定位
|
||
|
||
新架构中,系统拆分为通用 `Task` 服务、`LMS` 服务、`WMS` 服务。
|
||
|
||
其中:
|
||
|
||
- `LMS`:生产内部搬运业务,例如 AGV 搬运某个架子、托盘、料车到某个生产站点、缓存位、对接位;
|
||
- `WMS`:仓储出入库业务,例如入库、出库、移库、堆垛机搬运、AGV 和立库设备联动;
|
||
- `Task`:统一任务服务,负责任务创建记录、任务状态流转、调度下发外部系统、接收外部反馈、任务日志、重试和补偿。
|
||
|
||
旧架构中 `AbstractAcsTask` 同时承担了任务创建、点位计算、外部下发、完成业务、取消业务等职责。新架构建议将其拆分,避免 Task 服务反向依赖 LMS/WMS 的业务实现。
|
||
|
||
## 2. 总体设计目标
|
||
|
||
1. Task 服务成为通用任务中台,只处理任务生命周期和外部系统交互;
|
||
2. LMS/WMS 保留各自业务语义和业务数据处理能力;
|
||
3. 不再跨服务使用 Java 类名 `handle_class`;
|
||
4. 使用稳定的 `handler_code` 标识业务处理器;
|
||
5. 任务完成、取消时,由 Task 服务通知业务归属服务执行业务回调;
|
||
6. 支持 AGV、堆垛机、ACS、WCS 等多种外部系统;
|
||
7. 支持同步 RPC 回调,也能平滑演进到 MQ 事件回调;
|
||
8. 支持幂等、重试、补偿和人工干预。
|
||
|
||
## 3. 核心拆分思想
|
||
|
||
旧版一个 `AbstractAcsTask` 拆成三层能力:
|
||
|
||
```text
|
||
业务任务创建层:LMS/WMS
|
||
负责业务校验、点位计算、业务参数准备、调用 Task 创建任务
|
||
|
||
通用任务执行层:Task
|
||
负责任务状态、任务下发、外部反馈、任务日志、重试补偿
|
||
|
||
业务结果处理层:LMS/WMS
|
||
负责完成/取消后的业务确认、库存、单据、点位、分配明细处理
|
||
```
|
||
|
||
对应代码抽象:
|
||
|
||
```text
|
||
LMS/WMS:BusinessTaskCreator,可选
|
||
Task:ExternalTaskDispatcher
|
||
LMS/WMS:TaskBizCallbackHandler
|
||
```
|
||
|
||
## 4. 服务职责边界
|
||
|
||
### 4.1 LMS 服务职责
|
||
|
||
LMS 负责生产内部搬运任务的业务语义,例如:
|
||
|
||
- 判断某个架子是否允许搬运;
|
||
- 判断目标站点、缓存位、对接位是否可用;
|
||
- 生成生产搬运业务记录;
|
||
- 调用 Task 服务创建搬运任务;
|
||
- 任务完成后更新生产业务状态;
|
||
- 任务取消后回滚生产占用、点位锁定、业务单据状态。
|
||
|
||
### 4.2 WMS 服务职责
|
||
|
||
WMS 负责仓储出入库任务的业务语义,例如:
|
||
|
||
- 入库、出库、移库业务校验;
|
||
- 库位分配、库存预占、出入库单据状态维护;
|
||
- 调用 Task 服务创建 AGV/堆垛机/输送线任务;
|
||
- 任务完成后确认出入库或移库;
|
||
- 任务取消后释放库位、回滚库存预占、恢复单据状态。
|
||
|
||
### 4.3 Task 服务职责
|
||
|
||
Task 服务只处理通用任务能力:
|
||
|
||
- 保存任务主表;
|
||
- 保存任务明细或任务步骤;
|
||
- 管理任务状态机;
|
||
- 根据 `external_system` 选择外部系统下发器;
|
||
- 下发 AGV/ACS/WCS/堆垛机任务;
|
||
- 接收外部系统反馈;
|
||
- 根据 `owner_service` 通知 LMS/WMS 做业务回调;
|
||
- 记录任务日志;
|
||
- 处理重试、超时和补偿。
|
||
|
||
Task 服务不直接处理 LMS/WMS 的业务表,不直接注入 LMS/WMS 的业务 Service。
|
||
|
||
## 5. 模块依赖设计
|
||
|
||
推荐依赖方向:
|
||
|
||
```text
|
||
lms-server -> task-api
|
||
wms-server -> task-api
|
||
|
||
task-server -> task-api
|
||
task-server -> lms-api,可选,仅 RPC 回调需要
|
||
task-server -> wms-api,可选,仅 RPC 回调需要
|
||
```
|
||
|
||
禁止依赖:
|
||
|
||
```text
|
||
task-server -> lms-server
|
||
task-server -> wms-server
|
||
```
|
||
|
||
如果采用 MQ 事件方式,Task 服务甚至可以不依赖 `lms-api`、`wms-api`,只发布标准任务事件。
|
||
|
||
## 6. 新版任务标识设计
|
||
|
||
旧版:
|
||
|
||
```text
|
||
handle_class = org.nl.b_lms.sch.tasks.TwoInTask
|
||
```
|
||
|
||
新版:
|
||
|
||
```text
|
||
owner_service = LMS
|
||
biz_type = PRODUCTION_TRANSFER
|
||
handler_code = LMS_RACK_TO_STATION
|
||
biz_id = LMS 业务记录 ID
|
||
```
|
||
|
||
或 WMS:
|
||
|
||
```text
|
||
owner_service = WMS
|
||
biz_type = INBOUND
|
||
handler_code = WMS_INBOUND_STACKER
|
||
biz_id = WMS 入库单/分配明细 ID
|
||
```
|
||
|
||
字段含义:
|
||
|
||
| 字段 | 含义 |
|
||
| --- | --- |
|
||
| `owner_service` | 任务归属业务服务,决定完成/取消回调给谁 |
|
||
| `biz_type` | 业务任务类型,用于查询、统计和权限控制 |
|
||
| `handler_code` | 业务回调处理器编码,业务服务内部使用 |
|
||
| `biz_id` | 业务侧记录 ID,用于回查业务数据 |
|
||
| `external_system` | 外部执行系统,例如 AGV、ACS、WCS、STACKER |
|
||
| `external_task_type` | 外部系统任务类型 |
|
||
|
||
## 7. 数据模型建议
|
||
|
||
### 7.1 task_task 主表
|
||
|
||
| 字段 | 说明 |
|
||
| --- | --- |
|
||
| `id` | Task 服务任务 ID |
|
||
| `task_no` | 任务编号 |
|
||
| `owner_service` | LMS/WMS |
|
||
| `biz_type` | 业务类型 |
|
||
| `biz_id` | 业务侧 ID |
|
||
| `handler_code` | 业务回调处理器编码 |
|
||
| `external_system` | 外部系统 |
|
||
| `external_task_type` | 外部任务类型 |
|
||
| `status` | 任务状态 |
|
||
| `priority` | 优先级 |
|
||
| `start_point_code` | 起点 |
|
||
| `end_point_code` | 终点 |
|
||
| `vehicle_code` | 载具、架子、托盘、料车等 |
|
||
| `callback_status` | 回调状态 |
|
||
| `request_payload` | 创建任务扩展参数 |
|
||
| `dispatch_payload` | 下发外部系统参数 |
|
||
| `result_payload` | 外部反馈参数 |
|
||
| `error_msg` | 异常信息 |
|
||
|
||
### 7.2 task_task_log 日志表
|
||
|
||
记录每次状态变化、下发、反馈、回调、取消、重试。
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 说明 |
|
||
| --- | --- |
|
||
| `task_id` | 任务 ID |
|
||
| `event_type` | CREATE/DISPATCH/FEEDBACK/CALLBACK/CANCEL/RETRY |
|
||
| `from_status` | 原状态 |
|
||
| `to_status` | 新状态 |
|
||
| `request_json` | 请求参数 |
|
||
| `response_json` | 响应参数 |
|
||
| `success` | 是否成功 |
|
||
| `error_msg` | 错误信息 |
|
||
|
||
### 7.3 task_callback_log 回调日志表
|
||
|
||
用于保证业务回调幂等和补偿。
|
||
|
||
| 字段 | 说明 |
|
||
| --- | --- |
|
||
| `task_id` | 任务 ID |
|
||
| `owner_service` | LMS/WMS |
|
||
| `handler_code` | 业务处理器编码 |
|
||
| `event_type` | FINISH/CANCEL/EXECUTING |
|
||
| `status` | PROCESSING/SUCCESS/FAILED |
|
||
| `retry_count` | 重试次数 |
|
||
| `error_msg` | 失败原因 |
|
||
|
||
## 8. 状态机设计
|
||
|
||
推荐 Task 服务状态:
|
||
|
||
| 状态 | 含义 |
|
||
| --- | --- |
|
||
| `CREATED` | 已创建 |
|
||
| `READY` | 可下发 |
|
||
| `ISSUING` | 下发中 |
|
||
| `ISSUED` | 已下发 |
|
||
| `EXECUTING` | 外部执行中 |
|
||
| `FINISHED_PENDING_CALLBACK` | 外部完成,等待业务完成回调 |
|
||
| `FINISHED` | 业务完成后最终完成 |
|
||
| `CANCEL_PENDING_EXTERNAL` | 等待外部系统取消 |
|
||
| `CANCEL_PENDING_CALLBACK` | 外部取消成功,等待业务取消回调 |
|
||
| `CANCELLED` | 业务取消后最终取消 |
|
||
| `FAILED` | 失败 |
|
||
|
||
核心原则:
|
||
|
||
```text
|
||
外部系统完成 != 业务完成
|
||
外部系统取消 != 业务取消完成
|
||
```
|
||
|
||
因此必须有 `PENDING_CALLBACK` 中间状态。
|
||
|
||
## 9. 接口设计
|
||
|
||
### 9.1 Task 创建接口
|
||
|
||
```text
|
||
POST /rpc-api/task/create
|
||
```
|
||
|
||
请求核心字段:
|
||
|
||
```json
|
||
{
|
||
"ownerService": "LMS",
|
||
"bizType": "PRODUCTION_TRANSFER",
|
||
"bizId": "LMS-BIZ-10001",
|
||
"handlerCode": "LMS_RACK_TO_STATION",
|
||
"externalSystem": "AGV",
|
||
"externalTaskType": "MOVE",
|
||
"startPointCode": "CACHE_A01",
|
||
"endPointCode": "STATION_01",
|
||
"vehicleCode": "RACK_001",
|
||
"priority": 1,
|
||
"requestPayload": {}
|
||
}
|
||
```
|
||
|
||
WMS 入库示例:
|
||
|
||
```json
|
||
{
|
||
"ownerService": "WMS",
|
||
"bizType": "INBOUND",
|
||
"bizId": "IN-DIS-10001",
|
||
"handlerCode": "WMS_INBOUND_STACKER",
|
||
"externalSystem": "STACKER",
|
||
"externalTaskType": "INBOUND",
|
||
"startPointCode": "IN_PORT_01",
|
||
"endPointCode": "A010101",
|
||
"vehicleCode": "PALLET_001",
|
||
"priority": 5,
|
||
"requestPayload": {}
|
||
}
|
||
```
|
||
|
||
### 9.2 外部系统反馈接口
|
||
|
||
```text
|
||
POST /api/task/feedback
|
||
```
|
||
|
||
```json
|
||
{
|
||
"taskId": 10001,
|
||
"externalTaskNo": "ACS-TASK-001",
|
||
"externalEventId": "EVT-001",
|
||
"status": "FINISHED",
|
||
"payload": {}
|
||
}
|
||
```
|
||
|
||
### 9.3 取消任务接口
|
||
|
||
```text
|
||
POST /rpc-api/task/cancel
|
||
```
|
||
|
||
```json
|
||
{
|
||
"taskId": 10001,
|
||
"reason": "人工取消"
|
||
}
|
||
```
|
||
|
||
### 9.4 业务回调接口
|
||
|
||
第一阶段建议 RPC,同步调用业务服务:
|
||
|
||
```text
|
||
POST /rpc-api/lms/task-callback/handle
|
||
POST /rpc-api/wms/task-callback/handle
|
||
```
|
||
|
||
```json
|
||
{
|
||
"taskId": 10001,
|
||
"taskNo": "T202607130001",
|
||
"eventType": "FINISH",
|
||
"bizType": "PRODUCTION_TRANSFER",
|
||
"bizId": "LMS-BIZ-10001",
|
||
"handlerCode": "LMS_RACK_TO_STATION",
|
||
"payload": {}
|
||
}
|
||
```
|
||
|
||
## 10. Task 服务核心代码抽象
|
||
|
||
### 10.1 外部系统下发器
|
||
|
||
```java
|
||
public interface ExternalTaskDispatcher {
|
||
String getExternalSystem();
|
||
DispatchResult dispatch(TaskDO task);
|
||
CancelExternalResult cancelExternal(TaskDO task);
|
||
}
|
||
```
|
||
|
||
实现示例:
|
||
|
||
```text
|
||
AgvTaskDispatcher
|
||
AcsTaskDispatcher
|
||
WcsTaskDispatcher
|
||
StackerTaskDispatcher
|
||
```
|
||
|
||
Task 服务根据 `external_system` 选择对应 dispatcher。
|
||
|
||
### 10.2 业务回调通知器
|
||
|
||
```java
|
||
public interface TaskBizCallbackNotifier {
|
||
CallbackResult notifyFinish(TaskDO task);
|
||
CallbackResult notifyCancel(TaskDO task);
|
||
CallbackResult notifyExecuting(TaskDO task);
|
||
}
|
||
```
|
||
|
||
第一阶段可实现为 RPC:
|
||
|
||
```text
|
||
RpcTaskBizCallbackNotifier
|
||
```
|
||
|
||
第二阶段可实现为 MQ:
|
||
|
||
```text
|
||
MqTaskBizCallbackNotifier
|
||
```
|
||
|
||
## 11. LMS/WMS 业务回调 handler 设计
|
||
|
||
业务服务内部定义:
|
||
|
||
```java
|
||
public interface TaskBizCallbackHandler {
|
||
String getHandlerCode();
|
||
void onTaskFinished(TaskCallbackRequest request);
|
||
void onTaskCancelled(TaskCallbackRequest request);
|
||
default void onTaskExecuting(TaskCallbackRequest request) {}
|
||
}
|
||
```
|
||
|
||
LMS 示例:
|
||
|
||
```java
|
||
@Component
|
||
public class LmsRackToStationCallbackHandler implements TaskBizCallbackHandler {
|
||
@Override
|
||
public String getHandlerCode() {
|
||
return "LMS_RACK_TO_STATION";
|
||
}
|
||
|
||
@Override
|
||
public void onTaskFinished(TaskCallbackRequest request) {
|
||
// 更新生产搬运记录完成
|
||
// 更新架子当前位置
|
||
// 释放起点占用
|
||
// 占用目标站点或更新目标站点状态
|
||
}
|
||
|
||
@Override
|
||
public void onTaskCancelled(TaskCallbackRequest request) {
|
||
// 回滚生产搬运记录
|
||
// 释放目标站点锁定
|
||
// 恢复架子原状态
|
||
}
|
||
}
|
||
```
|
||
|
||
WMS 示例:
|
||
|
||
```java
|
||
@Component
|
||
public class WmsInboundStackerCallbackHandler implements TaskBizCallbackHandler {
|
||
@Override
|
||
public String getHandlerCode() {
|
||
return "WMS_INBOUND_STACKER";
|
||
}
|
||
|
||
@Override
|
||
public void onTaskFinished(TaskCallbackRequest request) {
|
||
// 入库确认
|
||
// 更新库存
|
||
// 更新库位状态
|
||
// 更新入库单和分配明细
|
||
}
|
||
|
||
@Override
|
||
public void onTaskCancelled(TaskCallbackRequest request) {
|
||
// 回滚入库分配
|
||
// 释放库位预占
|
||
// 恢复入库单状态
|
||
}
|
||
}
|
||
```
|
||
|
||
业务服务内建立分发器:
|
||
|
||
```java
|
||
@Service
|
||
public class TaskBizCallbackDispatcher {
|
||
private final Map<String, TaskBizCallbackHandler> handlerMap;
|
||
|
||
public void dispatch(TaskCallbackRequest request) {
|
||
TaskBizCallbackHandler handler = handlerMap.get(request.getHandlerCode());
|
||
if (handler == null) {
|
||
throw new IllegalArgumentException("未找到处理器:" + request.getHandlerCode());
|
||
}
|
||
if ("FINISH".equals(request.getEventType())) {
|
||
handler.onTaskFinished(request);
|
||
} else if ("CANCEL".equals(request.getEventType())) {
|
||
handler.onTaskCancelled(request);
|
||
} else if ("EXECUTING".equals(request.getEventType())) {
|
||
handler.onTaskExecuting(request);
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 12. 典型流程
|
||
|
||
### 12.1 LMS 生产搬运任务
|
||
|
||
```text
|
||
LMS 判断架子 RACK_001 要去 STATION_01
|
||
-> LMS 锁定目标站点
|
||
-> LMS 创建生产搬运业务记录
|
||
-> LMS 调用 Task.createTask,handler_code = LMS_RACK_TO_STATION
|
||
-> Task 下发 AGV
|
||
-> AGV 反馈执行中,Task 更新 EXECUTING,可选通知 LMS
|
||
-> AGV 反馈完成,Task 更新 FINISHED_PENDING_CALLBACK
|
||
-> Task 回调 LMS
|
||
-> LMS 更新架子位置、站点状态、业务记录完成
|
||
-> Task 更新 FINISHED
|
||
```
|
||
|
||
### 12.2 WMS 入库任务
|
||
|
||
```text
|
||
WMS 入库单分配库位 A010101
|
||
-> WMS 锁定库位,生成入库分配
|
||
-> WMS 调用 Task.createTask,handler_code = WMS_INBOUND_STACKER
|
||
-> Task 下发堆垛机/AGV
|
||
-> 外部系统反馈完成
|
||
-> Task 更新 FINISHED_PENDING_CALLBACK
|
||
-> Task 回调 WMS
|
||
-> WMS 确认入库、更新库存、更新库位、更新单据
|
||
-> Task 更新 FINISHED
|
||
```
|
||
|
||
### 12.3 取消任务
|
||
|
||
```text
|
||
用户取消任务
|
||
-> Task 判断状态
|
||
-> 如果已下发,调用外部系统取消
|
||
-> 外部取消成功后 Task 更新 CANCEL_PENDING_CALLBACK
|
||
-> Task 回调 LMS/WMS
|
||
-> LMS/WMS 执行业务回滚
|
||
-> Task 更新 CANCELLED
|
||
```
|
||
|
||
## 13. 幂等与事务
|
||
|
||
### 13.1 Task 幂等
|
||
|
||
外部反馈按以下维度幂等:
|
||
|
||
```text
|
||
task_id + external_event_id + status
|
||
```
|
||
|
||
同一个完成反馈不能重复触发业务完成。
|
||
|
||
### 13.2 业务幂等
|
||
|
||
LMS/WMS 按以下维度幂等:
|
||
|
||
```text
|
||
task_id + event_type
|
||
```
|
||
|
||
如果业务回调已经成功,再次收到直接返回成功。
|
||
|
||
### 13.3 跨服务一致性
|
||
|
||
不做分布式事务,采用最终一致性:
|
||
|
||
1. Task 更新为 `PENDING_CALLBACK`;
|
||
2. Task 调用 LMS/WMS;
|
||
3. LMS/WMS 在本地事务内完成业务更新和回调日志;
|
||
4. Task 更新最终状态;
|
||
5. 失败则进入重试或人工补偿。
|
||
|
||
## 14. 开发落地步骤
|
||
|
||
### 第一阶段:基础 RPC 版本
|
||
|
||
1. 在 `task-api` 定义任务创建、取消、回调 DTO;
|
||
2. 在 `task-server` 建任务主表、任务日志表、回调日志表;
|
||
3. 实现 Task 创建接口;
|
||
4. 实现 `ExternalTaskDispatcher` 和 AGV/ACS/堆垛机下发器;
|
||
5. 实现外部反馈接口;
|
||
6. 实现 RPC 业务回调通知器;
|
||
7. 在 LMS/WMS 实现 `TaskBizCallbackHandler` 和分发器;
|
||
8. 打通 LMS 生产搬运和 WMS 入库两个典型任务。
|
||
|
||
### 第二阶段:增强可靠性
|
||
|
||
1. 增加回调失败重试定时任务;
|
||
2. 增加外部下发失败重试;
|
||
3. 增加人工补偿页面;
|
||
4. 增加状态流转校验;
|
||
5. 增加任务日志和链路追踪。
|
||
|
||
### 第三阶段:MQ 演进
|
||
|
||
1. Task 服务发布任务完成/取消事件;
|
||
2. LMS/WMS 消费事件执行业务;
|
||
3. 业务服务回调 Task 确认处理结果;
|
||
4. RPC 和 MQ 可按任务类型配置切换。
|
||
|
||
## 15. 最终建议
|
||
|
||
不要把 LMS/WMS 的业务 `xxxTask` 子类放到 Task 服务,也不要让 Task 服务依赖 LMS/WMS server。
|
||
|
||
推荐把旧 `AbstractAcsTask` 拆成:
|
||
|
||
```text
|
||
Task 服务:ExternalTaskDispatcher,负责外部系统下发和取消
|
||
LMS/WMS:TaskBizCallbackHandler,负责业务完成和业务取消
|
||
```
|
||
|
||
旧 `handle_class` 改为:
|
||
|
||
```text
|
||
owner_service + handler_code
|
||
```
|
||
|
||
这样既保留了旧版“不同任务走不同处理器”的扩展性,又满足新架构下服务边界清晰、依赖方向正确、任务服务通用化的目标。
|