refactor: make jsatl12 optional

This commit is contained in:
lingniu
2026-07-01 07:33:06 +08:00
parent 4f83cd2792
commit 0987bb4718
6 changed files with 44 additions and 7 deletions

View File

@@ -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-appJSATL12 附件上传没有独立生产 app也不在 Portainer 和 Woodpecker 活跃镜像列表中。
- **Decision**:
1. `protocol-jsatl12` 不进入默认 Maven reactor。
2. JSATL12 仅保留在 `optional-attachments` profile需要附件上传能力时显式构建。
3. 默认优化和验证优先覆盖活跃接入链路,附件上传能力保持源码可用但不增加默认构建面。
- **Consequences**: 默认构建更轻,生产部署边界更清晰;附件上传相关测试需要通过 `-Poptional-attachments` 显式运行。

View File

@@ -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/sP99 < 50 ms - **高并发低延迟**Netty + Disruptor + Java 25 虚拟线程;目标单节点 ≥ 5 万 msg/sP99 < 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 1078808 信令按需桥接 + 常用下行信令编码 + TCP/UDP RTP 媒体流分段归档 + 事件 metadata 内部 VIN + 坏 RTP 统一 RawArchive/Passthrough + 归档失败兜底 + SIM 身份映射) │ │ ├── protocol-jt1078/ JT/T 1078808 信令按需桥接 + 常用下行信令编码 + 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`

View File

@@ -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>

View File

@@ -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`.

View File

@@ -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 信达 PushLegacy only") .contains("## ADR-004 信达 PushLegacy 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");
} }

View File

@@ -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>