82 lines
3.9 KiB
Markdown
82 lines
3.9 KiB
Markdown
---
|
||
name: 修复海康请求ID重复
|
||
overview: 确认根因是多实例部署下 `SnowflakeIdGenerator` 固定 `workerId=1, datacenterId=1`,同毫秒生成相同雪花 ID,导致并发海康请求的 `X-LR-REQUEST-ID` 重复。计划将海康 HTTP 请求 ID 改为 UUID 生成,避免跨实例碰撞。
|
||
todos:
|
||
- id: fix-request-id
|
||
content: MachineIntegrationAutoConfiguration:X-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 递增号段。
|