cursor/plans/修复海康请求id重复_693ddb99.plan.md

82 lines
3.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: 修复海康请求ID重复
overview: 确认根因是多实例部署下 `SnowflakeIdGenerator` 固定 `workerId=1, datacenterId=1`,同毫秒生成相同雪花 ID导致并发海康请求的 `X-LR-REQUEST-ID` 重复。计划将海康 HTTP 请求 ID 改为 UUID 生成,避免跨实例碰撞。
todos:
- id: fix-request-id
content: MachineIntegrationAutoConfigurationX-LR-REQUEST-ID 改为 ASRS + UUID去掉 SnowflakeIdGenerator
status: pending
- id: compile-verify
content: 编译 baoshi-robot-integration 并并发验证请求 ID 唯一性
status: pending
isProject: false
---
# 修复海康 X-LR-REQUEST-ID 多实例重复
## 问题确认
两条并发海康 `task/submit` 请求日志:
- 不同 traceId`5190815295754e028131f7bc18502911` / `5bf388d7211f4001bf7248d417240543`
- 不同任务号:`MC2072288711575474302` / `MC2072288711575474213`
- 不同线程:`robot-async-12` / `robot-async-16`
- **相同** `X-LR-REQUEST-ID``ASRS2072313718577958912`
当前生成逻辑在 [`MachineIntegrationAutoConfiguration.java`](baoshi-robot/baoshi-robot-integration/src/main/java/com/baoshi/robot/machine/integration/autoconfigure/MachineIntegrationAutoConfiguration.java)
```java
String requestId = "ASRS" + SnowflakeIdGenerator.generate();
```
[`SnowflakeIdGenerator`](baoshi-common/common/src/main/java/com/baoshi/common/util/SnowflakeIdGenerator.java) 写死 `IdUtil.getSnowflake(1, 1)`。单 JVM 内 `nextId()` 是 synchronized 的,不会重复;**多实例同 workerId/datacenterId 时,同毫秒会产出相同 ID**。
```mermaid
sequenceDiagram
participant PodA as PodA_robot_async_12
participant PodB as PodB_robot_async_16
participant HK as Hikvision_RCS
PodA->>PodA: Snowflake(1,1) -> 2072313718577958912
PodB->>PodB: Snowflake(1,1) -> 2072313718577958912
PodA->>HK: X-LR-REQUEST-ID=ASRS2072313718577958912
PodB->>HK: X-LR-REQUEST-ID=ASRS2072313718577958912
```
## 修复方案(推荐)
**海康 HTTP 请求 ID 改用 UUID**,与项目内同类场景保持一致:
- [`WebClientUtil`](baoshi-wms/src/main/java/com/baoshi/wms/util/WebClientUtil.java) 对 `X-LR-REQUEST-ID` 已用 `UUID.randomUUID().toString().replace("-", "")`
- 旧版 [`HikServiceClient`](baoshi-robot/baoshi-robot-hik/src/main/java/com/baoshi/robot/hik/client/HikServiceClient.java) 用 `RobotCodeGenerator`,跨实例仍有同毫秒碰撞风险
**变更点1 个文件,约 2 行)**
修改 [`MachineIntegrationAutoConfiguration.java`](baoshi-robot/baoshi-robot-integration/src/main/java/com/baoshi/robot/machine/integration/autoconfigure/MachineIntegrationAutoConfiguration.java)
```java
// 替换
String requestId = "ASRS" + SnowflakeIdGenerator.generate();
// 为
String requestId = "ASRS" + UUID.randomUUID().toString().replace("-", "");
```
- 移除 `SnowflakeIdGenerator` import增加 `java.util.UUID` import
- 日志与 `.header(requestIdHeader, requestId)` 逻辑不变
- 重试分支(`doCall` 递归)每次仍会生成新 UUID行为合理
**为何不用给 Snowflake 配 workerId**
- `X-LR-REQUEST-ID` 只是外部请求幂等/追踪头,不需要时间有序
- UUID 零配置、跨实例天然唯一,改动最小
- 配置 workerId 需要 K8s/部署侧配合,且 [`CreateCodeUtil.machineTaskChainCode()`](baoshi-common-dao/src/main/java/com/baoshi/common/base/util/CreateCodeUtil.java) 也共用同一 `SnowflakeIdGenerator`,若要彻底修复 MC 号碰撞需另做专项
## 验证
1. 编译 `baoshi-robot-integration` 模块
2. 本地或测试环境并发触发 2+ 个海康 `createTask`,确认日志中 `X-LR-REQUEST-ID` 均不同
3. 多 Pod 部署下复测(重点场景)
## 后续风险(本次不改动)
`MC` 任务链号同样使用 `SnowflakeIdGenerator.generate()`,多实例极端并发下理论上也可能重复。若线上曾出现 MC 号冲突,建议单独立项:按实例配置 workerId 或改为 Redis 递增号段。