e8150114df78958520b85ae3a17c2f16a28fdf51
Same peer that uses the Guangdong fuel-cell extension also emits a proprietary 0x83 block that is NOT in the published v1.0 spec table 8. Empirically it follows a TLV layout: type(1) + length(2) + value(N). Adds: - InfoBlock.GuangdongFc.VendorTlv(typeCode, declaredLength, payload) record + permits clause + InfoBlockType.GD_FC_VENDOR_TLV enum entry. - GdFcVendorTlvBlockParser: typeCode injected via constructor, reads 2B big-endian length then exactly that many payload bytes. Defends against declaredLength > remaining by truncating to remaining. - AutoConfig: registers `new GdFcVendorTlvBlockParser(0x83)` under the guangdong-fc catalog entry. Future unknown vendor typeCodes can be added by inserting more instances; no new class required. Critical correctness property — the parser is strictly bounded by the length field, so BodyParser's main loop continues processing blocks that come AFTER the TLV instead of having them swallowed by the old generic Raw fallback. Three unit tests cover this: - parsesPayloadOfDeclaredLengthExactly: round-trip a 5-byte payload - doesNotSwallowSubsequentBlocksWhenChainedInBodyParser: feeds a body containing 0x83 TLV(4B) followed by a 0x01 standard Vehicle block; asserts both blocks are parsed - truncatesPayloadIfDeclaredLengthExceedsRemaining: defensive case Test count: 32 -> 35. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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 |
| 会话缓存 | Caffeine + Redis 兜底 |
| 熔断/限流 | Resilience4j 2 |
| 可观测 | Micrometer + Prometheus + OpenTelemetry |
| 冷存 | S3 / OSS / 本地 |
| 构建 | Maven + Spotless + ArchUnit |
模块划分
lingniu-vehicle-ingest/
├── bom/ 依赖版本统一
├── ingest-api/ SPI + sealed 领域事件 + 注解
├── ingest-codec-common/ 公共编解码工具(BCD/CRC/BCC/bit utils)
├── ingest-core/ Pipeline / Dispatcher / Disruptor / Session 桥
├── session-core/ 设备会话 + 鉴权 + Token
├── observability/ metrics / tracing / health
├── sink-mq/ Kafka producer + Protobuf Envelope
├── sink-archive/ 原始报文冷存
├── protocol-gb32960/ GB/T 32960
├── protocol-jt808/ JT/T 808
├── protocol-jt1078/ JT/T 1078
├── protocol-jsatl12/ 苏标主动安全报警附件
├── inbound-mqtt/ MQTT 接入(宇通等)
├── inbound-xinda-push/ 信达 Push 接入(重写)
├── command-gateway/ HTTP → 设备下行命令
└── bootstrap-all/ 一体化启动
快速开始
# 要求:JDK 25, Maven 3.9+
mvn -v
mvn clean install -DskipTests
cd bootstrap-all && mvn spring-boot:run
迁移说明
本项目是 lingniu-vehicle-data-reception 的 v2 重构,采用 strangler fig 渐进式迁移,旧项目保留只读参考。迁移路径与决策参见 ../REFRACTOR_PLAN.md。
核心原则
- 本服务不写业务库:历史、行程、在线检测、里程统计全部由 Kafka 下游消费者实现
- 协议即插拔:每个
protocol-*/inbound-*都可独立开关(lingniu.ingest.<name>.enabled) - 顺序保证:同一 VIN 严格有序(Disruptor hash + Kafka 分区 key)
- 幂等消费:Envelope 带
eventId,下游去重 - 原始可回放:
vehicle.raw.archivetopic + 对象存储
Description
Languages
Java
81.7%
Go
12.3%
Python
5.9%