docs: align tdengine verification with active apps

This commit is contained in:
lingniu
2026-07-01 12:46:24 +08:00
parent dc481e8653
commit 252aff984c
2 changed files with 83 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
# Vehicle Ingest TDengine 链路验收手册
这份手册用于验收当前 32960/JT808 接入重构链路:
这份手册用于验收当前 GB32960/JT808/Yutong MQTT 接入重构链路:
1. 协议 App 接收 TCP 报文。
2. 协议 App 归档原始帧元数据,并把事件信封发布到 Kafka。
@@ -34,14 +34,16 @@ export TDENGINE_TELEMETRY_FIELDS_ENABLED=false
## 构建
```bash
mvn -pl modules/apps/jt808-ingest-app,modules/apps/gb32960-ingest-app,modules/apps/vehicle-history-app -am package -Dmaven.test.skip=true
mvn -pl :gb32960-ingest-app,:jt808-ingest-app,:yutong-mqtt-app,:vehicle-history-app,:vehicle-analytics-app -am package -Dmaven.test.skip=true
```
预期产物:
- `modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar`
- `modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar`
- `modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar`
- `modules/apps/yutong-mqtt-app/target/yutong-mqtt-app.jar`
- `modules/apps/vehicle-history-app/target/vehicle-history-app.jar`
- `modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar`
## 启动 JT808 接入服务,监听 808 端口
@@ -81,6 +83,26 @@ curl -sS http://127.0.0.1:20100/actuator/health/readiness
lsof -nP -iTCP:32960 -sTCP:LISTEN
```
## 启动 Yutong MQTT 接入服务
```bash
HTTP_PORT=20500 \
YUTONG_MQTT_ENABLED=true \
YUTONG_MQTT_AUTO_STARTUP=true \
KAFKA_CONSUMER_ENABLED=false \
java -jar modules/apps/yutong-mqtt-app/target/yutong-mqtt-app.jar
```
验证:
```bash
curl -sS http://127.0.0.1:20500/actuator/health
curl -sS http://127.0.0.1:20500/actuator/health/liveness
curl -sS http://127.0.0.1:20500/actuator/health/readiness
```
预期:健康检查为 `UP`,并且 Kafka 中 `vehicle.raw.mqtt-yutong.v1``vehicle.event.mqtt-yutong.v1` 能随真实 MQTT 消息增长。
## 启动 TDengine 版历史服务
```bash
@@ -102,6 +124,26 @@ curl -sS http://127.0.0.1:20200/v3/api-docs \
预期:健康检查为 `UP`OpenAPI 中包含通用位置分页查询和 RAW 帧查询接口。`/api/event-history/telemetry/fields` 只有在 `TDENGINE_TELEMETRY_FIELDS_ENABLED=true` 后才会暴露;默认高吞吐模式不暴露该接口,也不会持续写入逐字段宽表。
## 启动 JT808 指标统计服务
```bash
HTTP_PORT=20300 \
KAFKA_CONSUMER_ENABLED=true \
VEHICLE_STAT_ENABLED=true \
VEHICLE_STAT_JT808_MILEAGE_ENABLED=true \
java -jar modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar
```
验证:
```bash
curl -sS http://127.0.0.1:20300/actuator/health
curl -sS http://127.0.0.1:20300/actuator/health/liveness
curl -sS http://127.0.0.1:20300/actuator/health/readiness
```
预期:健康检查为 `UP`JT808 位置帧中有 GPS 总里程时,服务按差值法写入 MySQL `vehicle_stat_metric``daily_mileage_km` 指标。
## 本机 launchctl 部署
当前本机生产验证建议使用仓库模板生成 plist
@@ -115,6 +157,7 @@ deploy/local/launchctl/
- `jt808-ingest-app` 监听 TCP `808`HTTP `20400`
- `gb32960-ingest-app` 监听 TCP `32960`HTTP `20100`
- `vehicle-history-app` 监听 HTTP `20200`
- Yutong MQTT 与 `vehicle-analytics-app` 可以按上面的 jar 启动命令手工验收Portainer/ECS 生产部署已包含这两个服务。
- history 热查询只依赖 Kafka 和 TDengine `raw_frames`;本地模板不会给 history 注入 `SINK_ARCHIVE_PATH`
- GB32960/JT808 接入服务可以继续使用 `SINK_ARCHIVE_PATH` 保存原始 `.bin` 冷备,但这不是 history API 的实时查询前置条件。
- 替换 jar 前先 `launchctl bootout`,再复制 jar 和 `launchctl bootstrap`,避免 KeepAlive 在 jar 拷贝中途重启。
@@ -138,16 +181,24 @@ curl -sS http://127.0.0.1:20400/actuator/health/readiness
curl -sS http://127.0.0.1:20100/actuator/health
curl -sS http://127.0.0.1:20100/actuator/health/liveness
curl -sS http://127.0.0.1:20100/actuator/health/readiness
curl -sS http://127.0.0.1:20500/actuator/health
curl -sS http://127.0.0.1:20500/actuator/health/liveness
curl -sS http://127.0.0.1:20500/actuator/health/readiness
curl -sS http://127.0.0.1:20200/actuator/health
curl -sS http://127.0.0.1:20200/actuator/health/liveness
curl -sS http://127.0.0.1:20200/actuator/health/readiness
curl -sS http://127.0.0.1:20300/actuator/health
curl -sS http://127.0.0.1:20300/actuator/health/liveness
curl -sS http://127.0.0.1:20300/actuator/health/readiness
```
Swagger
- JT808 ingest: `http://127.0.0.1:20400/swagger-ui/index.html`
- GB32960 ingest: `http://127.0.0.1:20100/swagger-ui/index.html`
- Yutong MQTT ingest: `http://127.0.0.1:20500/swagger-ui/index.html`
- History query: `http://127.0.0.1:20200/swagger-ui/index.html`
- Analytics metrics: `http://127.0.0.1:20300/swagger-ui/index.html`
## Kafka Topic 验证
@@ -157,6 +208,8 @@ Swagger
- `vehicle.raw.gb32960.v1`
- `vehicle.event.jt808.v1`
- `vehicle.raw.jt808.v1`
- `vehicle.event.mqtt-yutong.v1`
- `vehicle.raw.mqtt-yutong.v1`
使用 Kafka CLI 或管理工具检查 topic 是否存在,并确认 history consumer group 在测试流量后没有持续堆积。默认 `KAFKA_GROUP_HISTORY=vehicle-history` 时,实际 group 会拆成:
@@ -164,6 +217,8 @@ Swagger
- `vehicle-history-gb32960-raw`
- `vehicle-history-jt808-event`
- `vehicle-history-jt808-raw`
- `vehicle-history-yutong-mqtt-event`
- `vehicle-history-yutong-mqtt-raw`
## JT808 实时转发验收
@@ -245,7 +300,7 @@ SELECT COUNT(*) FROM telemetry_fields;
- `com.lingniu.gb32960.32960`: `gb32960-ingest-app`TCP `32960`HTTP `20100`
- `com.lingniu.vehicle-history.jt808`: `vehicle-history-app`HTTP `20200`
健康检查已确认三个服务均返回 `{"status":"UP"}`
当次健康检查均返回 `{"status":"UP"}`
可重复运行 live 验收工具:

View File

@@ -137,7 +137,7 @@ class PortainerComposeResourceLimitsTest {
String runbook = Files.readString(repositoryRoot()
.resolve("docs/operations/vehicle-ingest-tdengine-verification.md"));
for (String httpPort : List.of("20100", "20400", "20200")) {
for (String httpPort : List.of("20100", "20400", "20500", "20200", "20300")) {
assertThat(runbook)
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/liveness")
.contains("curl -sS http://127.0.0.1:" + httpPort + "/actuator/health/readiness");
@@ -316,6 +316,29 @@ class PortainerComposeResourceLimitsTest {
.doesNotContain("repackaged all three app jars");
}
@Test
void tdengineVerificationRunbookDocumentsAllActiveProductionApps() throws IOException {
String runbook = Files.readString(repositoryRoot()
.resolve("docs/operations/vehicle-ingest-tdengine-verification.md"));
String activeBuildCommand =
"mvn -pl :gb32960-ingest-app,:jt808-ingest-app,:yutong-mqtt-app,:vehicle-history-app,:vehicle-analytics-app -am package -Dmaven.test.skip=true";
assertThat(runbook)
.contains(activeBuildCommand)
.contains("modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar")
.contains("modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar")
.contains("modules/apps/yutong-mqtt-app/target/yutong-mqtt-app.jar")
.contains("modules/apps/vehicle-history-app/target/vehicle-history-app.jar")
.contains("modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar")
.contains("vehicle.raw.mqtt-yutong.v1")
.contains("vehicle.event.mqtt-yutong.v1")
.contains("vehicle-history-yutong-mqtt-event")
.contains("vehicle-history-yutong-mqtt-raw")
.contains("vehicle-analytics-app")
.doesNotContain("mvn -pl modules/apps/jt808-ingest-app,modules/apps/gb32960-ingest-app,modules/apps/vehicle-history-app")
.doesNotContain("健康检查已确认三个服务");
}
@Test
void architectureDocsNameKafkaInsteadOfGenericMq() throws IOException {
String decisions = Files.readString(repositoryRoot().resolve("DECISIONS.md"));