Files
lingniu-vehicle-ingest/docs/operations/vehicle-ingest-tdengine-verification.md
lingniu ef9ac327fe
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
docs: document local ingest deployment verification
2026-06-29 16:18:52 +08:00

269 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Vehicle Ingest TDengine 链路验收手册
这份手册用于验收当前 32960/JT808 接入重构链路:
1. 协议 App 接收 TCP 报文。
2. 协议 App 归档原始帧元数据,并把事件信封发布到 Kafka。
3. `vehicle-history-app` 消费 Kafka。
4. history 写入 raw、location、telemetry field 到 TDengine。
5. Swagger/API 通过 TDengine 做历史分页查询。
每一步都必须执行命令并检查输出后,才能标记为已验证。
## 必需运行参数
启动服务前先设置:
```bash
export KAFKA_BROKERS=114.55.58.251:9092
export TDENGINE_HISTORY_ENABLED=true
export TDENGINE_JDBC_URL='jdbc:TAOS-RS://<tdengine-host>:6041/vehicle_history'
export TDENGINE_USERNAME=root
export TDENGINE_PASSWORD='<tdengine-password>'
export TDENGINE_MIN_IDLE=0
export TDENGINE_MAX_POOL_SIZE=32
```
`TDENGINE_MIN_IDLE=0` 用于减少冷启动时 TDengine 连接重试日志。TDengine 地址稳定后,再按生产并发调大连接池。
## 构建
```bash
mvn -pl modules/apps/jt808-ingest-app,modules/apps/gb32960-ingest-app,modules/apps/vehicle-history-app -am package -DskipTests
```
预期产物:
- `modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar`
- `modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar`
- `modules/apps/vehicle-history-app/target/vehicle-history-app.jar`
## 启动 JT808 接入服务,监听 808 端口
```bash
HTTP_PORT=20400 \
JT808_PORT=808 \
KAFKA_CONSUMER_ENABLED=false \
java -jar modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar
```
验证:
```bash
curl -sS http://127.0.0.1:20400/actuator/health
lsof -nP -iTCP:808 -sTCP:LISTEN
```
预期:健康检查为 `UP`,并且 Java 进程监听 TCP `808`
## 启动 GB32960 接入服务
```bash
HTTP_PORT=20100 \
GB32960_PORT=32960 \
KAFKA_CONSUMER_ENABLED=false \
java -jar modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar
```
验证:
```bash
curl -sS http://127.0.0.1:20100/actuator/health
lsof -nP -iTCP:32960 -sTCP:LISTEN
```
## 启动 TDengine 版历史服务
```bash
HTTP_PORT=20200 \
KAFKA_CONSUMER_ENABLED=true \
EVENT_FILE_STORE_ENABLED=true \
EVENT_FILE_STORE_PATH=./target/tdengine-verification/event-store \
SINK_ARCHIVE_PATH=./target/tdengine-verification/archive \
java -jar modules/apps/vehicle-history-app/target/vehicle-history-app.jar
```
验证:
```bash
curl -sS http://127.0.0.1:20200/actuator/health
curl -sS http://127.0.0.1:20200/v3/api-docs \
| grep -E '/api/event-history/jt808/locations|/api/event-history/telemetry/fields'
```
预期:健康检查为 `UP`OpenAPI 中包含这两个 TDengine 查询接口。
## 本机 launchctl 部署
当前本机生产验证建议使用仓库模板生成 plist
```bash
deploy/local/launchctl/
```
关键约束:
- `jt808-ingest-app` 监听 TCP `808`HTTP `20482`
- `gb32960-ingest-app` 监听 TCP `32960`HTTP `20100`
- `vehicle-history-app` 监听 HTTP `20200`
- 三个服务必须共用同一个 `SINK_ARCHIVE_PATH`,否则 TDengine 中的 `raw_uri` 能入库,但 history API 无法按 `archive://...` 读取原始帧。
- 替换 jar 前先 `launchctl bootout`,再复制 jar 和 `launchctl bootstrap`,避免 KeepAlive 在 jar 拷贝中途重启。
健康检查:
```bash
curl -sS http://127.0.0.1:20482/actuator/health
curl -sS http://127.0.0.1:20100/actuator/health
curl -sS http://127.0.0.1:20200/actuator/health
```
Swagger
- JT808 ingest: `http://127.0.0.1:20482/swagger-ui/index.html`
- GB32960 ingest: `http://127.0.0.1:20100/swagger-ui/index.html`
- History query: `http://127.0.0.1:20200/swagger-ui/index.html`
## Kafka Topic 验证
历史服务必须消费事件 topic 和 raw topic
- `vehicle.event.gb32960.v1`
- `vehicle.raw.gb32960.v1`
- `vehicle.event.jt808.v1`
- `vehicle.raw.jt808.v1`
使用 Kafka CLI 或管理工具检查 topic 是否存在,并确认 `vehicle-history` consumer group 在测试流量后没有持续堆积。
## JT808 实时转发验收
如果外部平台已经把 JT808 报文转发到本机 TCP `808`,至少观察 60 秒日志和 Kafka 数据。
必须拿到以下证据:
- `jt808-ingest-app` 日志显示接入连接或解析到上游消息 ID。
- Kafka 的 `vehicle.event.jt808.v1``vehicle.raw.jt808.v1` 有新增记录。
- `vehicle-history-app` 日志没有持续出现 consumer 或 TDengine 写入失败。
消费完成后,使用已知终端手机号查询:
```bash
curl -sS 'http://127.0.0.1:20200/api/event-history/jt808/locations?phone=<phone>&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
```
预期:响应包含 `items`,并且每条记录包含 `eventTime``phone``longitude``latitude``speedKmh``rawUri``metadataJson`
## Telemetry Field 查询验收
查询 GB32960 字段历史:
```bash
curl -sS 'http://127.0.0.1:20200/api/event-history/telemetry/fields?protocol=GB32960&vin=<vin>&fieldKey=<field-key>&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
```
查询 JT808 字段历史。没有 VIN 映射时,优先使用 `phone`
```bash
curl -sS 'http://127.0.0.1:20200/api/event-history/telemetry/fields?protocol=JT808&phone=<phone>&fieldKey=location.speed_kmh&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
```
预期:响应包含 `items`,可能包含 `nextCursor`。下一页使用 `nextCursor` 里的 `cursorTs``cursorId` 查询。
## TDengine 直接检查
使用 TDengine CLI 或 JDBC 客户端检查超级表和子表是否创建:
```sql
USE vehicle_history;
SHOW STABLES;
SELECT COUNT(*) FROM raw_frames;
SELECT COUNT(*) FROM vehicle_locations;
SELECT COUNT(*) FROM telemetry_fields;
```
预期:
- `raw_frames``vehicle_locations``telemetry_fields` 存在。
- 有实时流量后,计数持续增加。
## 失败语义
- TDengine 不可达时TDengine 查询接口应该返回 HTTP `503`,消息类似 `tdengine history query failed`
- TDengine 未启用时TDengine 专属接口不应该出现在 OpenAPI 中。
- 路径不存在时API 层应该返回 HTTP `404`,而不是泛化的存储失败。
## 2026-06-29 本机实时链路验证结果
运行服务:
- `com.lingniu.jt808.808`: `jt808-ingest-app`TCP `808`HTTP `20482`
- `com.lingniu.gb32960.32960`: `gb32960-ingest-app`TCP `32960`HTTP `20100`
- `com.lingniu.vehicle-history.jt808`: `vehicle-history-app`HTTP `20200`
健康检查已确认三个服务均返回 `{"status":"UP"}`
JT808 真实转发链路已验证:
- 本机 TCP `808` 有外部平台持续发送 JT808 报文。
- `vehicle.raw.jt808.v1``vehicle.event.jt808.v1` 被 history 消费。
- `raw_frames``protocol='JT808'` 的真实行数已超过 `6000`
- `vehicle_locations``protocol='JT808'` 的位置行数已超过 `1900`
- `telemetry_fields``protocol='JT808'` 的字段行数已超过 `15000`
- 最新样例包含终端号 `13079963310`、消息 ID `512``archive://2026/06/29/JT808/...` 原始帧引用。
复查 SQL
```sql
USE vehicle_ts;
SELECT COUNT(*) FROM raw_frames WHERE protocol = 'JT808';
SELECT COUNT(*) FROM vehicle_locations WHERE protocol = 'JT808';
SELECT COUNT(*) FROM telemetry_fields WHERE protocol = 'JT808';
SELECT event_time, vehicle_key, phone, message_id, raw_uri
FROM raw_frames
WHERE protocol = 'JT808'
ORDER BY event_time DESC
LIMIT 5;
```
复查 API
```bash
curl -sS 'http://127.0.0.1:20200/api/event-history/jt808/locations?phone=13079963296&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
```
GB32960 链路已用合成实时帧验证:
- TCP `32960` 返回 GB32960 `2323` ACK。
- `raw_frames` 中测试 VIN `LTEST202606290001` 已有 `2` 条 raw 记录。
- `telemetry_fields` 中测试 VIN `LTEST202606290001` 已有 `34` 条字段记录。
- latest raw 包含 `archive://2026/06/29/GB32960/LTEST202606290001/...`
- snapshots API 可查到 `speedKmh=62.4``totalMileageKm=223456.7``longitude=116.397128``latitude=39.916527`
复查 SQL
```sql
USE vehicle_ts;
SELECT COUNT(*) FROM raw_frames
WHERE protocol = 'GB32960' AND vin = 'LTEST202606290001';
SELECT COUNT(*) FROM telemetry_fields
WHERE protocol = 'GB32960' AND vin = 'LTEST202606290001';
SELECT event_time, vin, raw_uri, raw_id
FROM raw_frames
WHERE protocol = 'GB32960' AND vin = 'LTEST202606290001'
ORDER BY event_time DESC
LIMIT 5;
```
复查 API
```bash
curl -sS 'http://127.0.0.1:20200/api/event-history/gb32960/snapshots?vin=LTEST202606290001&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
curl -sS 'http://127.0.0.1:20200/api/event-history/gb32960/snapshots/fields?vin=LTEST202606290001&fields=VEHICLE.speedKmh,VEHICLE.totalMileageKm,POSITION_V2016.longitude,POSITION_V2016.latitude&dateFrom=2026-06-29T00:00:00%2B08:00&dateTo=2026-06-29T23:59:59%2B08:00&limit=10'
```
## 当前注意事项
- 当前本机使用 TDengine WebSocket JDBC例如 `jdbc:TAOS-WS://<tdengine-host>:6041/vehicle_ts`
- `KAFKA_CONSUMER_AUTO_OFFSET_RESET=latest` 适合生产接入新流量;如果要回放历史 Kafka 数据,需要切换 consumer group 或重置 offset。
- `vehicle-history-app` raw 和 event 使用不同 consumer bindingraw consumer 必须开启,否则 `raw_frames` 不会持续增长。
- JT808 设备没有 VIN 映射时,`vehicle_key` 使用 `jt808:<phone>`,后续维护注册/VIN 映射后再反写 VIN。