feat: 二阶段
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# MQ 消息体序列化结构变更检测 — 方案
|
||||
|
||||
> 版本:v0.3
|
||||
> 版本:v0.4
|
||||
> 日期:2026-07-15
|
||||
> 状态:**Phase M1 已实现**(MQ01/MQ02 + MQ-K01/MQ-K02);M2/M3 未启动
|
||||
> 状态:**Phase M1 + M2 已实现**(生产侧 MQ01~05 / MQ-K01~K04 + 读侧 MQ-R)
|
||||
> 关联:复用 `serialization-schema-checker` 的 Schema 提取、Diff、企微通知与 CI 框架
|
||||
> 业务样本仓:`jnpf-java-cloud`(**RocketMQ + Kafka**)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
在 push 时静态分析 **消息体类型的序列化 Schema** 是否相对对比区间发生变更,覆盖 **RocketMQ + Kafka**,并复用现有企微通知 / notify|block 能力。
|
||||
|
||||
### 1.3 非目标(本方案首版)
|
||||
### 1.3 非目标
|
||||
|
||||
- 不连接真实 Broker,不拉取积压消息做运行时校验
|
||||
- 不解析依赖 jar 内消息类型(仅本仓 `src/main/java`)
|
||||
@@ -56,8 +56,9 @@
|
||||
| `rocketMQTemplate.syncSend(dest, dto)` | 高(如钱包扣费) | **纳入** |
|
||||
| `asyncSend` / `syncSendOrderly` 等 | 中 | **纳入** |
|
||||
| `convertAndSend` | 视封装而定 | **纳入** |
|
||||
| 先 `JSON.toJSONString` 再发 String | 较低 | unwrap 后取类型 |
|
||||
| 只发 `String` / `byte[]` / `MessageExt` | 有 | **默认忽略** |
|
||||
| `MessageBuilder.withPayload` 再 send | 中(如 IM 延时消息) | **纳入**(MQ04) |
|
||||
| 先 `JSON.toJSONString` 再发 String | 较低 | unwrap 后取类型(MQ05) |
|
||||
| 只发 `String` / `byte[]` / 无泛型 `Message` | 有 | **默认忽略** |
|
||||
|
||||
样本(资金钱包):
|
||||
|
||||
@@ -74,6 +75,8 @@ public class WalletDeductConsumer implements RocketMQListener<WalletDeductReq> {
|
||||
|------|----------|------|
|
||||
| `kafkaTemplate.send(topic, dto)` | 中(值班食安项等) | **纳入** |
|
||||
| `kafkaTemplate.send(topic, List<Xxx>)` | 中(巡店食安项列表) | **纳入**(rootArray) |
|
||||
| `kafkaTemplate.send(ProducerRecord)` | 中 | **纳入**(MQ-K03) |
|
||||
| 先 JSON 再 `send(topic, json)` | 较低 | unwrap(MQ-K04) |
|
||||
| `@KafkaListener` + `String` + `JSONObject.parseObject(..., Xxx.class)` | 有(数据分析中差评) | **读侧补强 MQ-R** |
|
||||
| `KafkaTopicUtil` 仅创建 Topic | 有(租户) | **忽略**(无消息体) |
|
||||
|
||||
@@ -118,6 +121,8 @@ public void handleMessage(String message) {
|
||||
| RocketMQ | `RocketMQListener<T>`、`onMessage(T)` + `@RocketMQMessageListener` |
|
||||
| Kafka | `@KafkaListener` 方法参数类型;或方法内 `parseObject/parseArray(..., Xxx.class)`(与现有 W06 共享解析能力) |
|
||||
|
||||
开关:`detection.mq_read_hints_enabled`(默认 **true**)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 方案总览
|
||||
@@ -135,8 +140,8 @@ public void handleMessage(String message) {
|
||||
```text
|
||||
Git Diff → 变更 Java 文件
|
||||
├─ Redis:W01~W05 + W06 ← 已有
|
||||
└─ MQ:RocketMQ(MQ01~)+ Kafka(MQ-K*)
|
||||
+ Listener / parse 补强(MQ-R) ← 本方案
|
||||
└─ MQ:RocketMQ(MQ01~05)+ Kafka(MQ-K01~K04)
|
||||
+ Listener / parse 补强(MQ-R) ← 已实现
|
||||
↓
|
||||
同一套 TypeSchema / SchemaDiffer / Skeleton / WeCom
|
||||
```
|
||||
@@ -161,7 +166,7 @@ Git Diff → 变更 Java 文件
|
||||
| MQ01 | `rocketMQTemplate.syncSend(dest, payload, …)` | dest、payload 类型 |
|
||||
| MQ02 | `asyncSend` / `syncSendOrderly` / `sendOneWay` 等 | 同上 |
|
||||
| MQ03 | `convertAndSend(dest, payload)` | 同上 |
|
||||
| MQ04 | `MessageBuilder.withPayload(obj)` 再 send | payload 类型 |
|
||||
| MQ04 | `MessageBuilder.withPayload(obj)` 再 send,或 `Message<T>` | payload / `T` |
|
||||
| MQ05 | 先 `toJSONString`/`getObjectToString` 再 send String | unwrap 后类型 |
|
||||
|
||||
### 4.2 生产侧 — Kafka
|
||||
@@ -170,7 +175,7 @@ Git Diff → 变更 Java 文件
|
||||
|---------|------------|------|
|
||||
| MQ-K01 | `kafkaTemplate.send(topic, payload)` | topic、payload 类型 |
|
||||
| MQ-K02 | `kafkaTemplate.send(topic, key, payload)` | 同上(忽略分区 key) |
|
||||
| MQ-K03 | `send(ProducerRecord)` / `ListenableFuture` 封装若可解析 | topic + value 类型 |
|
||||
| MQ-K03 | `send(ProducerRecord)` | topic + value 类型 |
|
||||
| MQ-K04 | 先 JSON 序列化为 String 再 `send(topic, json)` | unwrap 后类型 |
|
||||
|
||||
Payload 为 `List<Xxx>` / `Collection` 时标记 **rootArray**,骨架为 JSON 数组(与 Redis List 一致)。
|
||||
@@ -187,7 +192,7 @@ Payload 为 `List<Xxx>` / `Collection` 时标记 **rootArray**,骨架为 JSON
|
||||
|---------|------|------|
|
||||
| MQ-R01 | `RocketMQListener<T>` / `@RocketMQMessageListener` | 补强同 destination 生产点 |
|
||||
| MQ-R02 | `@KafkaListener` + 参数类型 `T`(非 String) | 补强同 topic |
|
||||
| MQ-R03 | Listener 内 `parseObject`/`parseArray(..., Xxx.class)` | 补强(可复用 W06 检测器) |
|
||||
| MQ-R03 | Listener 内 `parseObject`/`parseArray(..., Xxx.class)` | 补强(复用 parse AST) |
|
||||
|
||||
开关:`detection.mq_read_hints_enabled`(默认 true)。
|
||||
|
||||
@@ -220,7 +225,6 @@ Payload 为 `List<Xxx>` / `Collection` 时标记 **rootArray**,骨架为 JSON
|
||||
|
||||
- 删除字段橙 `warning`;新增绿 `info`
|
||||
- destination 未解析时灰色提示
|
||||
- 可选后缀:「请评估消费积压与兼容反序列化」
|
||||
|
||||
「通道」字段用于区分中间件;若模板求简,可省略通道仅靠 Topic 形态区分。
|
||||
|
||||
@@ -272,37 +276,36 @@ manual_mappings:
|
||||
|
||||
## 7. 分阶段交付
|
||||
|
||||
### Phase M1 — MVP(RocketMQ + Kafka 基础投递)
|
||||
### Phase M1 — MVP(RocketMQ + Kafka 基础投递)✅
|
||||
|
||||
| 任务 | 说明 |
|
||||
|------|------|
|
||||
| MQ01/MQ02 | RocketMQ `syncSend` / `asyncSend` |
|
||||
| MQ-K01/MQ-K02 | Kafka `send(topic, payload)` / 三参 send |
|
||||
| destination 推断 | 字面量、常量、拼接;Kafka 动态 topic → `*` |
|
||||
| Schema Diff + 骨架通知 | 复用 ReportBuilder;可选「通道」行 |
|
||||
| Schema Diff + 骨架通知 | 复用 ReportBuilder;「通道」行 |
|
||||
| 夹具 | `fixtures/mq/rocket-wallet/`、`fixtures/mq/kafka-patrol/` |
|
||||
| 配置 | `mq_patterns`(含 MQ-K*)、`ignore.mq_destinations` |
|
||||
| List 根数组骨架 | `List<CheckItemDetailVo>` 等(与 M2 需求合并交付) |
|
||||
|
||||
**验收**:
|
||||
|
||||
1. 删 `WalletDeductReq` 字段 → 企微出现 RocketMQ Topic 骨架变更
|
||||
2. 删 `CheckItemDetailVo` 字段 → 企微出现 Kafka Topic 骨架变更
|
||||
|
||||
### Phase M2 — 增强
|
||||
### Phase M2 — 增强 ✅
|
||||
|
||||
| 任务 | 说明 |
|
||||
|------|------|
|
||||
| MQ03~MQ05、MQ-K03/K04 | convertAndSend、MessageBuilder、JSON 字符串发送、ProducerRecord |
|
||||
| MQ03~MQ05、MQ-K03/K04 | convertAndSend、MessageBuilder/`Message<T>`、JSON 字符串发送、ProducerRecord |
|
||||
| MQ-R01~R03 | RocketMQ Listener + Kafka `@KafkaListener` / parse 补强 |
|
||||
| List 根数组骨架 | 巡店 `List<CheckItemDetailVo>` 等 |
|
||||
| 夹具 | `fixtures/mq/rocket-im/`、`fixtures/mq/kafka-record/` |
|
||||
|
||||
### Phase M3 — 运营
|
||||
**验收**:
|
||||
|
||||
| 任务 | 说明 |
|
||||
|------|------|
|
||||
| 积压风险提示文案 | 统一提示评估消费 lag / 积压 |
|
||||
| 更多夹具 | 值班 Kafka、中差评 Listener、IM Favorite 等 |
|
||||
| 分 webhook / 标题前缀 | 缓存 vs MQ 可选拆分 |
|
||||
1. `MessageBuilder.withPayload(DutyImNotice)` + `asyncSend` → 命中 MQ04,改 VO 字段可告警
|
||||
2. `kafkaTemplate.send(ProducerRecord)` → 命中 MQ-K03
|
||||
3. Listener / `parseObject` 可补强同 Topic 弱类型生产点
|
||||
|
||||
---
|
||||
|
||||
@@ -312,10 +315,11 @@ manual_mappings:
|
||||
|------|------|
|
||||
| Kafka topic 按租户动态拼接 | 归一 `prefix:*`;`manual_mappings` |
|
||||
| RocketMQ / Kafka 混用同一 VO | 各投递点独立告警(符合预期) |
|
||||
| Listener 收 String、parse 在方法深处 | MQ-R03 + 复用 W06 AST |
|
||||
| Listener 收 String、parse 在方法深处 | MQ-R03 + parse AST |
|
||||
| 生产/消费跨模块对不齐 | 同仓索引 + destination 对齐;失败则仅写侧 |
|
||||
| Jackson / Fastjson / Kafka JsonSerializer 细节差 | 首版字段名;必要时方言或 mapping |
|
||||
| 只改消费未改生产类型 | 不告警(工具职责是消息体 Schema) |
|
||||
| `include_modules` 过窄 | 观察期扩大模块或置空全仓 |
|
||||
|
||||
---
|
||||
|
||||
@@ -334,6 +338,6 @@ manual_mappings:
|
||||
## 10. 下一步
|
||||
|
||||
1. ~~按 Phase M1 开发~~ **已完成**(MQ01/02 + MQ-K01/K02)
|
||||
2. Phase M2:MQ03~05、MQ-K03/K04、MQ-R 读侧补强
|
||||
3. 业务仓验收 Topic:`capital-topic:WALLET_DEDUCT`(RocketMQ)、巡店/值班 Kafka topic
|
||||
4. 观察期按需扩大 `include_modules`
|
||||
2. ~~按 Phase M2 开发~~ **已完成**(MQ03~05、MQ-K03/K04、MQ-R)
|
||||
3. 业务仓验收:`MessageBuilder` IM Topic、巡店/值班 Kafka、`capital-topic:WALLET_DEDUCT`
|
||||
4. 观察期按需扩大 `include_modules`
|
||||
|
||||
Reference in New Issue
Block a user