refactor: make jsatl12 optional
This commit is contained in:
11
DECISIONS.md
11
DECISIONS.md
@@ -32,7 +32,7 @@
|
|||||||
- **Consequences**: 信达 Push 现在不属于默认生产面;模块仅保留在 `legacy-xinda` profile,后续优化优先投向 GB32960、JT808、宇通 MQTT、历史和统计链路。
|
- **Consequences**: 信达 Push 现在不属于默认生产面;模块仅保留在 `legacy-xinda` profile,后续优化优先投向 GB32960、JT808、宇通 MQTT、历史和统计链路。
|
||||||
|
|
||||||
## ADR-005 JT1078 / JSATL12 进第一批
|
## ADR-005 JT1078 / JSATL12 进第一批
|
||||||
- **Status**: Accepted
|
- **Status**: Superseded by ADR-012
|
||||||
- **Decision**: 第一批迁移即覆盖 JT1078 信令 + JSATL12 报警附件上传
|
- **Decision**: 第一批迁移即覆盖 JT1078 信令 + JSATL12 报警附件上传
|
||||||
- **Consequences**: Phase 2 工期相应拉长;JSATL12 需要对象存储后端(本地 / S3 / OSS)
|
- **Consequences**: Phase 2 工期相应拉长;JSATL12 需要对象存储后端(本地 / S3 / OSS)
|
||||||
|
|
||||||
@@ -72,3 +72,12 @@
|
|||||||
2. Xinda Push 仅保留在 `legacy-xinda` profile,不进入默认 Maven reactor、Woodpecker 镜像发布和历史消费绑定。
|
2. Xinda Push 仅保留在 `legacy-xinda` profile,不进入默认 Maven reactor、Woodpecker 镜像发布和历史消费绑定。
|
||||||
3. `command-gateway` 和 JT1078 继续作为可选能力,通过 `optional-command-gateway` profile 显式启用。
|
3. `command-gateway` 和 JT1078 继续作为可选能力,通过 `optional-command-gateway` profile 显式启用。
|
||||||
- **Consequences**: 默认构建和部署保持精简;后续性能、可靠性、字段解析和存储优化都优先服务三条活跃协议链路。
|
- **Consequences**: 默认构建和部署保持精简;后续性能、可靠性、字段解析和存储优化都优先服务三条活跃协议链路。
|
||||||
|
|
||||||
|
## ADR-012 JSATL12 附件上传:Optional only
|
||||||
|
- **Status**: Accepted
|
||||||
|
- **Context**: 当前默认生产面只部署 GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app;JSATL12 附件上传没有独立生产 app,也不在 Portainer 和 Woodpecker 活跃镜像列表中。
|
||||||
|
- **Decision**:
|
||||||
|
1. `protocol-jsatl12` 不进入默认 Maven reactor。
|
||||||
|
2. JSATL12 仅保留在 `optional-attachments` profile,需要附件上传能力时显式构建。
|
||||||
|
3. 默认优化和验证优先覆盖活跃接入链路,附件上传能力保持源码可用但不增加默认构建面。
|
||||||
|
- **Consequences**: 默认构建更轻,生产部署边界更清晰;附件上传相关测试需要通过 `-Poptional-attachments` 显式运行。
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## 设计目标
|
## 设计目标
|
||||||
|
|
||||||
- **协议接入统一抽象**:GB/T 32960、JT/T 808、JT/T 1078、JSATL12、MQTT 全部变成可插拔 Inbound Adapter;信达 Push 仅保留为废弃兼容模块
|
- **协议接入统一抽象**:GB/T 32960、JT/T 808、Yutong MQTT 是默认生产接入;JT/T 1078、JSATL12 作为显式 profile 的可选能力;信达 Push 仅保留为废弃兼容模块
|
||||||
- **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关
|
- **原子能力化**:每个协议一个独立 Maven 模块 + 独立 AutoConfiguration + 独立配置开关
|
||||||
- **业务 / 实时彻底解耦**:本服务只负责 **收 → 解析 → 校验 → 规整 → 投递 Kafka**,不碰业务库
|
- **业务 / 实时彻底解耦**:本服务只负责 **收 → 解析 → 校验 → 规整 → 投递 Kafka**,不碰业务库
|
||||||
- **高并发低延迟**:Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/s,P99 < 50 ms
|
- **高并发低延迟**:Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/s,P99 < 50 ms
|
||||||
@@ -43,7 +43,7 @@ lingniu-vehicle-ingest/
|
|||||||
│ │ ├── protocol-gb32960/ GB/T 32960
|
│ │ ├── protocol-gb32960/ GB/T 32960
|
||||||
│ │ ├── protocol-jt808/ JT/T 808(统一身份映射 + 事件 metadata 内部 VIN + 注册/鉴权/心跳/注销/位置/批量位置/参数/属性/媒体/透传/未知上行和坏帧兜底/断链清理会话/下行分包)
|
│ │ ├── protocol-jt808/ JT/T 808(统一身份映射 + 事件 metadata 内部 VIN + 注册/鉴权/心跳/注销/位置/批量位置/参数/属性/媒体/透传/未知上行和坏帧兜底/断链清理会话/下行分包)
|
||||||
│ │ ├── protocol-jt1078/ JT/T 1078(808 信令按需桥接 + 常用下行信令编码 + TCP/UDP RTP 媒体流分段归档 + 事件 metadata 内部 VIN + 坏 RTP 统一 RawArchive/Passthrough + 归档失败兜底 + SIM 身份映射)
|
│ │ ├── protocol-jt1078/ JT/T 1078(808 信令按需桥接 + 常用下行信令编码 + TCP/UDP RTP 媒体流分段归档 + 事件 metadata 内部 VIN + 坏 RTP 统一 RawArchive/Passthrough + 归档失败兜底 + SIM 身份映射)
|
||||||
│ │ └── protocol-jsatl12/ 苏标主动安全报警附件(真实 DataPacket 分帧 + 附件流归档 + T1210 文件清单身份继承 + 9212 补传应答 + MediaMeta 引用事件 + 坏帧/坏信令/归档失败兜底)
|
│ │ └── protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile)
|
||||||
│ ├── inbound/
|
│ ├── inbound/
|
||||||
│ │ ├── inbound-mqtt/ MQTT 接入(endpoint 生命周期 + profile 注册扩展 + 统一身份映射 + PEM 双向 TLS + 未知 profile/解析失败/profile异常/连接订阅失败兜底 + 统一 UNKNOWN 身份 metadata)
|
│ │ ├── inbound-mqtt/ MQTT 接入(endpoint 生命周期 + profile 注册扩展 + 统一身份映射 + PEM 双向 TLS + 未知 profile/解析失败/profile异常/连接订阅失败兜底 + 统一 UNKNOWN 身份 metadata)
|
||||||
│ │ └── inbound-xinda-push/ 信达 Push 接入(废弃兼容模块,仅 -Plegacy-xinda 显式构建)
|
│ │ └── inbound-xinda-push/ 信达 Push 接入(废弃兼容模块,仅 -Plegacy-xinda 显式构建)
|
||||||
@@ -78,6 +78,8 @@ mvn -pl :jt808-ingest-app -am spring-boot:run
|
|||||||
|
|
||||||
信达 Push 已废弃,不参与默认 Maven reactor、CI、Portainer 部署和历史消费链路;如需兼容排查,可显式使用 `-Plegacy-xinda` 构建。
|
信达 Push 已废弃,不参与默认 Maven reactor、CI、Portainer 部署和历史消费链路;如需兼容排查,可显式使用 `-Plegacy-xinda` 构建。
|
||||||
|
|
||||||
|
JSATL12 附件上传不在默认 Maven reactor 中;需要时使用 `-Poptional-attachments` 构建。
|
||||||
|
|
||||||
## 迁移说明
|
## 迁移说明
|
||||||
|
|
||||||
本项目是 `lingniu-vehicle-data-reception` 的 v2 重构,采用 strangler fig 渐进式迁移,旧项目保留只读参考。迁移路径与决策参见 `../REFRACTOR_PLAN.md`。
|
本项目是 `lingniu-vehicle-data-reception` 的 v2 重构,采用 strangler fig 渐进式迁移,旧项目保留只读参考。迁移路径与决策参见 `../REFRACTOR_PLAN.md`。
|
||||||
|
|||||||
@@ -257,8 +257,9 @@
|
|||||||
<section>
|
<section>
|
||||||
<h2>一、系统定位</h2>
|
<h2>一、系统定位</h2>
|
||||||
<p>
|
<p>
|
||||||
当前项目不是业务库写入服务。它的核心职责是把 GB/T 32960、JT/T 808、JT/T 1078、JSATL12、
|
当前项目不是业务库写入服务。它的核心职责是把 GB/T 32960、JT/T 808、Yutong MQTT
|
||||||
MQTT 等不同来源的车辆数据统一转换为 <code>VehicleEvent</code> 和全字段 <code>TelemetrySnapshot</code>,
|
等默认生产来源的车辆数据统一转换为 <code>VehicleEvent</code> 和全字段 <code>TelemetrySnapshot</code>;
|
||||||
|
JT/T 1078、JSATL12 作为显式 profile 的可选能力保留,
|
||||||
再通过 Kafka、原始报文归档、TDengine 历史索引、Redis 热状态和独立统计模块交给下游业务。
|
再通过 Kafka、原始报文归档、TDengine 历史索引、Redis 热状态和独立统计模块交给下游业务。
|
||||||
</p>
|
</p>
|
||||||
<div class="summary-grid">
|
<div class="summary-grid">
|
||||||
@@ -564,7 +565,7 @@ flowchart LR
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>modules/protocols/protocol-jsatl12</td>
|
<td>modules/protocols/protocol-jsatl12</td>
|
||||||
<td>苏标主动安全报警附件接入。依赖 ArchiveStore 和 JT808 decoder;生产默认端口按旧接收服务对齐为 <code>7612</code>;附件 DataPacket 按旧服务真实布局 <code>01cd + 50B文件名 + offset + length + data</code> 分帧解析,不再把文件名前 4 字节误判为帧长;附件数据写 ArchiveStore 后通过 Dispatcher 产出 MediaMeta 引用事件,事件 metadata 保留 fileName、fileOffset、declaredChunkSizeBytes、archiveKey 和 archiveRef,便于附件明细查询、导出和补传诊断;内置附件状态机处理 T1210 文件清单、DataPacket 分块区间和 T1212 上传完成消息,数据分块会按 T1210 文件清单中的文件名继承手机号并通过共享身份解析器得到内部 VIN,入口 RawFrame、ArchivedChunk 和 MediaMeta 均保留 phone、vin、identityResolved、identitySource,只有找不到文件归属时才标记 UNKNOWN;按文件名合并无身份数据分块并返回 0x9212 完成/补传应答,补传应答包含缺失 offset/length 区间;附件归档失败会产出 JSATL12 Passthrough 错误事件并保留原始分块;JT_MESSAGE 信令复用 JT808 decoder 后进入 Dispatcher,桥接 RawFrame 使用共享身份解析后的内部 VIN并保留 phone、identityResolved、identitySource,坏 JT 信令入口 RawFrame 同样标记 UNKNOWN 身份;超长/畸形附件帧、未闭合超长 JT 信令和坏 JT 信令都以 JSATL12 Passthrough 兜底,附件帧异常同时标记 frameError 与统一 parseError/parseErrorMessage,保留原始字节、peer、长度和错误元数据,帧长和 worker 线程支持部署配置。</td>
|
<td>苏标主动安全报警附件接入(仅 <code>optional-attachments</code> profile 显式构建,不属于默认生产面)。依赖 ArchiveStore 和 JT808 decoder;端口按旧接收服务对齐为 <code>7612</code>;附件 DataPacket 按旧服务真实布局 <code>01cd + 50B文件名 + offset + length + data</code> 分帧解析,不再把文件名前 4 字节误判为帧长;附件数据写 ArchiveStore 后通过 Dispatcher 产出 MediaMeta 引用事件,事件 metadata 保留 fileName、fileOffset、declaredChunkSizeBytes、archiveKey 和 archiveRef,便于附件明细查询、导出和补传诊断;内置附件状态机处理 T1210 文件清单、DataPacket 分块区间和 T1212 上传完成消息,数据分块会按 T1210 文件清单中的文件名继承手机号并通过共享身份解析器得到内部 VIN,入口 RawFrame、ArchivedChunk 和 MediaMeta 均保留 phone、vin、identityResolved、identitySource,只有找不到文件归属时才标记 UNKNOWN;按文件名合并无身份数据分块并返回 0x9212 完成/补传应答,补传应答包含缺失 offset/length 区间;附件归档失败会产出 JSATL12 Passthrough 错误事件并保留原始分块;JT_MESSAGE 信令复用 JT808 decoder 后进入 Dispatcher,桥接 RawFrame 使用共享身份解析后的内部 VIN并保留 phone、identityResolved、identitySource,坏 JT 信令入口 RawFrame 同样标记 UNKNOWN 身份;超长/畸形附件帧、未闭合超长 JT 信令和坏 JT 信令都以 JSATL12 Passthrough 兜底,附件帧异常同时标记 frameError 与统一 parseError/parseErrorMessage,保留原始字节、peer、长度和错误元数据,帧长和 worker 线程支持部署配置。</td>
|
||||||
<td>主动安全附件流、JT808 信令帧。</td>
|
<td>主动安全附件流、JT808 信令帧。</td>
|
||||||
<td>归档文件、MediaMeta、JT808 统一事件、坏帧/坏信令/归档失败 Passthrough。</td>
|
<td>归档文件、MediaMeta、JT808 统一事件、坏帧/坏信令/归档失败 Passthrough。</td>
|
||||||
<td><span class="tag amber">附件归档</span><span class="tag">报警证据</span><span class="tag">信令复用</span><span class="tag">错误隔离</span></td>
|
<td><span class="tag amber">附件归档</span><span class="tag">报警证据</span><span class="tag">信令复用</span><span class="tag">错误隔离</span></td>
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ Xinda Push is legacy and is not part of the default production surface.
|
|||||||
It may remain in source for reference, but new optimization work should target
|
It may remain in source for reference, but new optimization work should target
|
||||||
the active protocols above.
|
the active protocols above.
|
||||||
|
|
||||||
|
JSATL12 attachment upload is also outside the default production reactor. Keep
|
||||||
|
it available through the `optional-attachments` profile until an attachment app
|
||||||
|
is explicitly deployed.
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
- Keep protocol IO, raw archive, history, latest-state, and statistics as
|
- Keep protocol IO, raw archive, history, latest-state, and statistics as
|
||||||
@@ -177,6 +181,8 @@ flowchart LR
|
|||||||
- Active production deployment contains GB32960, JT808, Yutong MQTT,
|
- Active production deployment contains GB32960, JT808, Yutong MQTT,
|
||||||
vehicle-history, and vehicle-analytics apps.
|
vehicle-history, and vehicle-analytics apps.
|
||||||
- Xinda Push is absent from default deployment and history consumer bindings.
|
- Xinda Push is absent from default deployment and history consumer bindings.
|
||||||
|
- JSATL12 is absent from the default Maven reactor and available through
|
||||||
|
`optional-attachments`.
|
||||||
- History APIs read from TDengine by default; Parquet/DuckDB is optional
|
- History APIs read from TDengine by default; Parquet/DuckDB is optional
|
||||||
compatibility only.
|
compatibility only.
|
||||||
- Raw frame queries can return complete parsed JSON through `payloadJson.parsed`.
|
- Raw frame queries can return complete parsed JSON through `payloadJson.parsed`.
|
||||||
|
|||||||
@@ -30,6 +30,17 @@ class MavenModuleProfileTest {
|
|||||||
"modules/apps/command-gateway");
|
"modules/apps/command-gateway");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void jsatl12AttachmentProtocolIsOptionalAndOutsideDefaultProductionReactor() throws Exception {
|
||||||
|
Document pom = rootPom();
|
||||||
|
|
||||||
|
assertThat(defaultModules(pom))
|
||||||
|
.doesNotContain("modules/protocols/protocol-jsatl12");
|
||||||
|
|
||||||
|
assertThat(profileModules(pom, "optional-attachments"))
|
||||||
|
.containsExactly("modules/protocols/protocol-jsatl12");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void xindaIsLegacyOnlyAndOutsideDefaultProductionReactor() throws Exception {
|
void xindaIsLegacyOnlyAndOutsideDefaultProductionReactor() throws Exception {
|
||||||
Document pom = rootPom();
|
Document pom = rootPom();
|
||||||
@@ -63,6 +74,7 @@ class MavenModuleProfileTest {
|
|||||||
.contains("Spring Boot " + projectProperty(pom, "spring-boot.version"))
|
.contains("Spring Boot " + projectProperty(pom, "spring-boot.version"))
|
||||||
.contains("Netty " + projectProperty(pom, "netty.version"))
|
.contains("Netty " + projectProperty(pom, "netty.version"))
|
||||||
.contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version"))
|
.contains("Eclipse Paho " + projectProperty(pom, "paho-mqtt.version"))
|
||||||
|
.contains("protocol-jsatl12/ 苏标主动安全报警附件(optional-attachments profile)")
|
||||||
.contains("event-file-store/ 可选兼容索引(旧 Parquet/DuckDB 路径)")
|
.contains("event-file-store/ 可选兼容索引(旧 Parquet/DuckDB 路径)")
|
||||||
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
|
.contains("vehicle-history-app/ TDengine 历史查询 + RAW JSON")
|
||||||
.contains("vehicle-analytics-app/ JT808 每日里程指标消费")
|
.contains("vehicle-analytics-app/ JT808 每日里程指标消费")
|
||||||
@@ -92,8 +104,10 @@ class MavenModuleProfileTest {
|
|||||||
assertThat(decisions)
|
assertThat(decisions)
|
||||||
.contains("## ADR-004 信达 Push:Legacy only")
|
.contains("## ADR-004 信达 Push:Legacy only")
|
||||||
.contains("## ADR-011 默认生产面:三协议接入 + 历史 + 统计")
|
.contains("## ADR-011 默认生产面:三协议接入 + 历史 + 统计")
|
||||||
|
.contains("## ADR-012 JSATL12 附件上传:Optional only")
|
||||||
.contains("GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app")
|
.contains("GB32960、JT808、Yutong MQTT、vehicle-history-app、vehicle-analytics-app")
|
||||||
.contains("Xinda Push 仅保留在 `legacy-xinda` profile")
|
.contains("Xinda Push 仅保留在 `legacy-xinda` profile")
|
||||||
|
.contains("JSATL12 仅保留在 `optional-attachments` profile")
|
||||||
.doesNotContain("## ADR-004 信达 Push:保留模块但彻底重写\n- **Status**: Accepted")
|
.doesNotContain("## ADR-004 信达 Push:保留模块但彻底重写\n- **Status**: Accepted")
|
||||||
.doesNotContain("Spring Boot 3.4.x");
|
.doesNotContain("Spring Boot 3.4.x");
|
||||||
}
|
}
|
||||||
|
|||||||
7
pom.xml
7
pom.xml
@@ -34,7 +34,6 @@
|
|||||||
<module>modules/services/vehicle-stat-service</module>
|
<module>modules/services/vehicle-stat-service</module>
|
||||||
<module>modules/protocols/protocol-gb32960</module>
|
<module>modules/protocols/protocol-gb32960</module>
|
||||||
<module>modules/protocols/protocol-jt808</module>
|
<module>modules/protocols/protocol-jt808</module>
|
||||||
<module>modules/protocols/protocol-jsatl12</module>
|
|
||||||
<module>modules/inbound/inbound-mqtt</module>
|
<module>modules/inbound/inbound-mqtt</module>
|
||||||
<module>modules/apps/gb32960-ingest-app</module>
|
<module>modules/apps/gb32960-ingest-app</module>
|
||||||
<module>modules/apps/jt808-ingest-app</module>
|
<module>modules/apps/jt808-ingest-app</module>
|
||||||
@@ -51,6 +50,12 @@
|
|||||||
<module>modules/apps/command-gateway</module>
|
<module>modules/apps/command-gateway</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>optional-attachments</id>
|
||||||
|
<modules>
|
||||||
|
<module>modules/protocols/protocol-jsatl12</module>
|
||||||
|
</modules>
|
||||||
|
</profile>
|
||||||
<profile>
|
<profile>
|
||||||
<id>legacy-xinda</id>
|
<id>legacy-xinda</id>
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
Reference in New Issue
Block a user