docs: clarify ingest and consumer persistence roles

This commit is contained in:
lingniu
2026-07-01 11:45:59 +08:00
parent 77d5aa4ef7
commit 5beb81f8cd
3 changed files with 12 additions and 6 deletions

View File

@@ -51,10 +51,10 @@
- 禁用 `synchronized`,使用 `ReentrantLock` 避免虚拟线程 pinning - 禁用 `synchronized`,使用 `ReentrantLock` 避免虚拟线程 pinning
- **Consequences**: 需开启 `jdk.VirtualThreadPinned` JFR 监控 - **Consequences**: 需开启 `jdk.VirtualThreadPinned` JFR 监控
## ADR-008 本服务不写业务库 ## ADR-008 协议接入应用不直接写业务库
- **Status**: Accepted - **Status**: Accepted
- **Decision**: 所有业务表vehicle_data_actual / history / travel / gps_data 等)不再由本服务写入 - **Decision**: GB32960、JT808、Yutong MQTT 等协议接入应用只负责收、解析、校验、规整和投递 Kafka不直接写业务表。
- **Consequences**: 需要新建消费服务 `vehicle-analytics-service` 承接;迁移期采用双跑对账 - **Consequences**: 业务落库由独立 Kafka 消费应用承接:`vehicle-history-app` 写入 TDengine 历史与 RAW JSON`vehicle-analytics-app` 写入 MySQL `vehicle_stat_metric`
## ADR-009 构建工具Maven ## ADR-009 构建工具Maven
- **Status**: Accepted - **Status**: Accepted

View File

@@ -6,7 +6,7 @@
- **协议接入统一抽象**GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 仅保留为废弃兼容模块 - **协议接入统一抽象**GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 仅保留为废弃兼容模块
- **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关 - **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关
- **业务 / 实时彻底解耦**本服务只负责 **收 → 解析 → 校验 → 规整 → 投递 Kafka**,不碰业务 - **业务 / 实时彻底解耦**协议接入应用只负责收、解析、校验、规整和投递 Kafka历史与统计由独立 Kafka 消费应用落
- **高并发低延迟**Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/sP99 < 50 ms - **高并发低延迟**Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/sP99 < 50 ms
- **可观测、可回放、可灰度**:统一 traceId、Envelope、幂等键、DLQ、原始报文冷存 - **可观测、可回放、可灰度**:统一 traceId、Envelope、幂等键、DLQ、原始报文冷存
@@ -95,7 +95,7 @@ Redis 最新状态查询不在默认 Maven reactor 中;需要时使用 `-Popti
## 核心原则 ## 核心原则
1. **本服务不写业务库**:历史、行程、在线检测、里程统计全部由 Kafka 下游消费者实现 1. **接入与业务落库分离**:协议接入应用只负责收、解析、校验、规整和投递 Kafka`vehicle-history-app` 写入 TDengine 历史与 RAW JSON`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`
2. **协议即插拔**:每个 `protocol-*` / `inbound-*` 都可独立开关(`lingniu.ingest.<name>.enabled` 2. **协议即插拔**:每个 `protocol-*` / `inbound-*` 都可独立开关(`lingniu.ingest.<name>.enabled`
3. **顺序保证**:同一 VIN 严格有序Disruptor hash + Kafka 分区 key 3. **顺序保证**:同一 VIN 严格有序Disruptor hash + Kafka 分区 key
4. **幂等消费**Envelope 带 `eventId`,下游去重 4. **幂等消费**Envelope 带 `eventId`,下游去重

View File

@@ -176,6 +176,8 @@ class MavenModuleProfileTest {
.contains("command-gateway/ 可选 HTTP → 设备下行命令optional-command-gateway profile") .contains("command-gateway/ 可选 HTTP → 设备下行命令optional-command-gateway profile")
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON") .contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
.contains("vehicle-analytics-app/ JT808 每日里程指标消费") .contains("vehicle-analytics-app/ JT808 每日里程指标消费")
.contains("协议接入应用只负责收、解析、校验、规整和投递 Kafka")
.contains("`vehicle-analytics-app` 将 JT808 `daily_mileage_km` 写入 MySQL `vehicle_stat_metric`")
.doesNotContain("Spring Boot 3.4") .doesNotContain("Spring Boot 3.4")
.doesNotContain("Netty 4.1") .doesNotContain("Netty 4.1")
.doesNotContain("HiveMQ MQTT Client") .doesNotContain("HiveMQ MQTT Client")
@@ -185,7 +187,9 @@ class MavenModuleProfileTest {
.doesNotContain("DuckDB") .doesNotContain("DuckDB")
.doesNotContain("Parquet") .doesNotContain("Parquet")
.doesNotContain("Parquet + DuckDB 文件型明细库") .doesNotContain("Parquet + DuckDB 文件型明细库")
.doesNotContain("车辆状态/日统计消费"); .doesNotContain("车辆状态/日统计消费")
.doesNotContain("本服务不写业务库")
.doesNotContain("里程统计全部由 Kafka 下游消费者实现");
} }
@Test @Test
@@ -237,6 +241,8 @@ class MavenModuleProfileTest {
.contains("JSATL12 仅保留在 `optional-attachments` profile") .contains("JSATL12 仅保留在 `optional-attachments` profile")
.contains("vehicle-state-service 仅保留在 `optional-latest-state` profile") .contains("vehicle-state-service 仅保留在 `optional-latest-state` profile")
.contains("raw-archive-store 仅保留在 `optional-raw-archive-store` profile") .contains("raw-archive-store 仅保留在 `optional-raw-archive-store` profile")
.contains("协议接入应用不直接写业务库")
.contains("`vehicle-analytics-app` 写入 MySQL `vehicle_stat_metric`")
.doesNotContain("event-file-store") .doesNotContain("event-file-store")
.doesNotContain("optional-event-file-store") .doesNotContain("optional-event-file-store")
.doesNotContain("## ADR-004 信达 Push保留模块但彻底重写\n- **Status**: Accepted") .doesNotContain("## ADR-004 信达 Push保留模块但彻底重写\n- **Status**: Accepted")