# lingniu-vehicle-ingest

> 羚牛车辆数据接入平台 v2

## 设计目标

- **协议接入统一抽象**：GB/T 32960、JT/T 808、JT/T 1078、JSATL12、MQTT、信达 Push 全部变成可插拔 Inbound Adapter
- **原子能力化**：每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关
- **业务 / 实时彻底解耦**：本服务只负责 **收 → 解析 → 校验 → 规整 → 投递 Kafka**，不碰业务库
- **高并发低延迟**：Netty + Disruptor + Java 25 虚拟线程；目标单节点 ≥ 5 万 msg/s，P99 < 50 ms
- **可观测、可回放、可灰度**：统一 traceId、Envelope、幂等键、DLQ、原始报文冷存

## 技术栈

| 类别 | 选型 |
|---|---|
| 语言 | Java **25** |
| 框架 | Spring Boot 3.4.x |
| 网络 | Netty 4.1 |
| 并发 | Disruptor 4 + 虚拟线程 + `StructuredTaskScope` |
| 消息队列 | **Kafka**（vin 分区，保证单车有序） |
| 线上消息格式 | **Protobuf**，调试走 JSON |
| MQTT 客户端 | HiveMQ MQTT Client |
| 会话缓存 | Redis 生产索引 + Caffeine 内存降级 |
| 熔断/限流 | Resilience4j 2 |
| 可观测 | Micrometer + Prometheus + OpenTelemetry |
| 冷存 | S3 / OSS / 本地 |
| 构建 | Maven + Spotless + ArchUnit |

## 模块划分

```
lingniu-vehicle-ingest/
├── modules/
│   ├── core/
│   │   ├── ingest-api/              SPI + sealed 领域事件 + 注解
│   │   ├── ingest-codec-common/     公共编解码工具（BCD/CRC/BCC/bit utils）
│   │   ├── ingest-core/             Pipeline / Dispatcher / Disruptor / Session 桥
│   │   ├── session-core/            设备会话 + 鉴权 + Token + Redis/Memory SessionStore
│   │   ├── vehicle-identity/        跨协议车辆身份解析 + 外部标识绑定（memory/file）
│   │   └── observability/           metrics / tracing / health
│   ├── protocols/
│   │   ├── protocol-gb32960/        GB/T 32960
│   │   ├── protocol-jt808/          JT/T 808（统一身份映射 + 事件 metadata 内部 VIN + 注册/鉴权/心跳/注销/位置/批量位置/参数/属性/媒体/透传/未知上行和坏帧兜底/断链清理会话/下行分包）
│   │   ├── protocol-jt1078/         JT/T 1078（808 信令按需桥接 + 常用下行信令编码 + TCP/UDP RTP 媒体流分段归档 + 事件 metadata 内部 VIN + 坏 RTP 统一 RawArchive/Passthrough + 归档失败兜底 + SIM 身份映射）
│   │   └── protocol-jsatl12/        苏标主动安全报警附件（真实 DataPacket 分帧 + 附件流归档 + T1210 文件清单身份继承 + 9212 补传应答 + MediaMeta 引用事件 + 坏帧/坏信令/归档失败兜底）
│   ├── inbound/
│   │   ├── inbound-mqtt/            MQTT 接入（endpoint 生命周期 + profile 注册扩展 + 统一身份映射 + PEM 双向 TLS + 未知 profile/解析失败/profile异常/连接订阅失败兜底 + 统一 UNKNOWN 身份 metadata）
│   │   └── inbound-xinda-push/      信达 Push 接入（统一身份映射 + 事件 metadata 内部 VIN + 未知业务 cmd/解析失败/启动配置失败/业务处理异常兜底）
│   ├── sinks/
│   │   ├── sink-mq/                 Kafka producer + Protobuf Envelope
│   │   ├── sink-archive/            原始报文冷存
│   │   └── event-file-store/        Parquet + DuckDB 文件型明细库
│   ├── services/
│   │   ├── event-history-service/   Kafka 全字段事件消费 + 历史查询/导出
│   │   ├── vehicle-state-service/   Kafka 全字段事件消费 + Redis 热状态查询
│   │   └── vehicle-stat-service/    Kafka 全字段事件消费 + 可配置日统计
│   └── apps/
│       ├── command-gateway/         HTTP → 设备下行命令（808 位置/参数/属性/控制/区域删除/报警确认 + 1078 音视频控制）
│       └── bootstrap-all/           一体化启动
├── docs/                           架构文档、模块图、实施计划
└── reference/                      参考资料
```

## 快速开始

```bash
# 要求：JDK 25, Maven 3.9+
mvn -v
mvn clean install -DskipTests
mvn -pl :bootstrap-all spring-boot:run
```

## 迁移说明

本项目是 `lingniu-vehicle-data-reception` 的 v2 重构，采用 strangler fig 渐进式迁移，旧项目保留只读参考。迁移路径与决策参见 `../REFRACTOR_PLAN.md`。

## 架构文档

- 目标架构：`docs/target-architecture.md`
- 内部字段模型：`docs/vehicle-telemetry-internal-fields.md`
- 模块与数据流：`docs/module-data-flow.html`

## 核心原则

1. **本服务不写业务库**：历史、行程、在线检测、里程统计全部由 Kafka 下游消费者实现
2. **协议即插拔**：每个 `protocol-*` / `inbound-*` 都可独立开关（`lingniu.ingest.<name>.enabled`）
3. **顺序保证**：同一 VIN 严格有序（Disruptor hash + Kafka 分区 key）
4. **幂等消费**：Envelope 带 `eventId`，下游去重
5. **原始可回放**：Dispatcher 会先发布 `RawArchive`，并把同一份 `rawArchiveKey/rawArchiveUri` 追加到业务事件 metadata；下游明细库、Kafka Envelope 和导出都使用 `archive://...` 逻辑 URI 追溯原始 bytes，实际文件由 `sink-archive`/`ArchiveStore` 管理；`event-file-store` 只额外保存 RawArchive 查询索引，不嵌入原始 bytes
