Files
lingniu-vehicle-ingest/DECISIONS.md
2026-07-01 07:42:16 +08:00

102 lines
6.5 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.
# 架构决策记录ADR 汇总)
> 本文件记录 lingniu-vehicle-ingest v2 的关键架构决策,后续每次重大调整追加条目(不删除旧条目)。
## ADR-001 MQ 选型Kafka
- **Status**: Accepted
- **Context**: 需要高吞吐、严格单车有序、成熟生态
- **Decision**: 使用 Kafka分区 key = VIN
- **Consequences**: 下游消费者需使用消费组 + 分区内顺序消费;不使用 RocketMQ 的事务/顺序特性
## ADR-002 线上消息格式Protobuf
- **Status**: Accepted
- **Context**: 需要向前兼容、体积小、性能好
- **Decision**: 线上用 Protobuf调试/诊断保留 JSON 序列化能力
- **Consequences**: 需维护 `.proto` schema`ingest-api` 模块负责生成 Java stub
## ADR-003 command-gateway 独立模块
- **Status**: Accepted
- **Context**: 下行命令链路不应与接入进程耦合
- **Decision**: 拆出独立 `command-gateway` 模块,复用 `session-core`;本次重构同步交付
- **Consequences**: HTTP 对外接口(原 JT808Controller / JT1078Controller迁移到此模块
## ADR-004 信达 PushLegacy only
- **Status**: Superseded by ADR-011
- **Context**: 旧实现硬编码凭证、无重连、0300/0401 空实现
- **Decision**:
1. 新模块 `inbound-xinda-push` 隔离第三方库 `gps-push-client`
2. 配置外置yml + env
3. 自动重连 + Resilience4j 熔断
4. 0200/0300/0401 **仅做协议解析**,转换为 `VehicleEvent` 后直接投 Kafka
5. **业务处理全部下沉到下游消费者**,本服务不再实现报警/透传业务逻辑
- **Consequences**: 信达 Push 现在不属于默认生产面;模块仅保留在 `legacy-xinda` profile后续优化优先投向 GB32960、JT808、宇通 MQTT、历史和统计链路。
## ADR-005 JT1078 / JSATL12 进第一批
- **Status**: Superseded by ADR-012
- **Decision**: 第一批迁移即覆盖 JT1078 信令 + JSATL12 报警附件上传
- **Consequences**: Phase 2 工期相应拉长JSATL12 需要对象存储后端(本地 / S3 / OSS
## ADR-006 部署形态GB32960 三应用拆分
- **Status**: Superseded
- **Context**: 原 `bootstrap-all` 一体化启动已被 GB32960 拆分部署替代
- **Decision**: 生产默认部署 `gb32960-ingest-app``vehicle-history-app``vehicle-analytics-app` 三个应用;旧 `bootstrap-all` 模块删除
- **Consequences**: CI/CD 分别构建三个镜像;协议接入、历史查询、统计消费可以独立发布和回滚
## ADR-007 Java 25 + 虚拟线程 + Disruptor
- **Status**: Accepted
- **Decision**:
- Netty EventLoop 只做解码与 RingBuffer 投递,严禁阻塞
- 业务 Handler 走虚拟线程(`Thread.ofVirtual()`
- 协议间背压通过 Disruptor RingBuffer 表达
- 禁用 `synchronized`,使用 `ReentrantLock` 避免虚拟线程 pinning
- **Consequences**: 需开启 `jdk.VirtualThreadPinned` JFR 监控
## ADR-008 本服务不写业务库
- **Status**: Accepted
- **Decision**: 所有业务表vehicle_data_actual / history / travel / gps_data 等)不再由本服务写入
- **Consequences**: 需要新建消费服务 `vehicle-analytics-service` 承接;迁移期采用双跑对账
## ADR-009 构建工具Maven
- **Status**: Accepted
- **Decision**: 沿用 Maven统一 BOM 管理版本Spotless 格式化ArchUnit 守护分层
## ADR-010 框架Spring Boot 3.5
- **Status**: Accepted
- **Decision**: Spring Boot 3.5.x支持 JDK 25AutoConfiguration 用于按需启停
## ADR-011 默认生产面:三协议接入 + 历史 + 统计
- **Status**: Accepted
- **Context**: 生产接入范围已经从 GB32960 三应用拆分,扩展为三条活跃接入链路和两个消费应用;信达 Push 已废弃,不应再出现在默认构建、部署或优化目标里。
- **Decision**:
1. 默认生产面包含 GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app。
2. Xinda Push 仅保留在 `legacy-xinda` profile不进入默认 Maven reactor、Woodpecker 镜像发布和历史消费绑定。
3. `command-gateway` 和 JT1078 继续作为可选能力,通过 `optional-command-gateway` profile 显式启用。
- **Consequences**: 默认构建和部署保持精简;后续性能、可靠性、字段解析和存储优化都优先服务三条活跃协议链路。
## ADR-012 JSATL12 附件上传Optional only
- **Status**: Accepted
- **Context**: 当前默认生产面只部署 GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-appJSATL12 附件上传没有独立生产 app也不在 Portainer 和 Woodpecker 活跃镜像列表中。
- **Decision**:
1. `protocol-jsatl12` 不进入默认 Maven reactor。
2. JSATL12 仅保留在 `optional-attachments` profile需要附件上传能力时显式构建。
3. 默认优化和验证优先覆盖活跃接入链路,附件上传能力保持源码可用但不增加默认构建面。
- **Consequences**: 默认构建更轻,生产部署边界更清晰;附件上传相关测试需要通过 `-Poptional-attachments` 显式运行。
## ADR-013 最新状态服务Optional only
- **Status**: Accepted
- **Context**: Redis 最新状态查询是独立消费能力,但当前默认 Portainer 部署和 Woodpecker 镜像发布只包含三条接入链路、history 和 analytics`vehicle-state-service` 没有独立 app也不应增加默认构建面。
- **Decision**:
1. `vehicle-state-service` 不进入默认 Maven reactor。
2. vehicle-state-service 仅保留在 `optional-latest-state` profile需要 Redis 最新状态查询能力时显式构建。
3. 默认优化和验证优先覆盖活跃接入、TDengine 历史和 MySQL 指标链路。
- **Consequences**: 默认构建和部署边界继续收窄;最新状态能力保持源码可用,但其测试需要通过 `-Poptional-latest-state` 显式运行。
## ADR-014 raw-archive-store 原型实现Optional only
- **Status**: Accepted
- **Context**: 默认生产 raw bytes 写入由 `sink-archive` 负责,历史查询通过 TDengine `raw_frames``archive://...` 引用追溯;`raw-archive-store` 当前只是独立读写接口和本地实现原型,没有默认 app 或 service 依赖。
- **Decision**:
1. `raw-archive-store` 不进入默认 Maven reactor。
2. raw-archive-store 仅保留在 `optional-raw-archive-store` profile需要验证本地读写原型时显式构建。
3. 默认生产链路继续以 `sink-archive`、Kafka raw topic、TDengine raw_frames 为准。
- **Consequences**: 默认构建少一个未部署模块;本地 raw archive 原型仍可通过 `-Poptional-raw-archive-store` 保留和验证。