chore: remove local service runners

This commit is contained in:
lingniu
2026-07-01 16:56:46 +08:00
parent ec4aed3ca9
commit 37844e4425
11 changed files with 83 additions and 935 deletions

View File

@@ -4,7 +4,7 @@ This runbook covers the default production runtimes: GB32960 ingest, JT808 inges
## Service Roles
| Service | Module | Role | Local ports |
| Service | Module | Role | Production ports |
| --- | --- | --- | --- |
| GB32960 ingest | `:gb32960-ingest-app` | Accept GB32960 TCP connections, decode/authenticate frames, produce raw and normalized records to Kafka, and send protocol ACKs after required Kafka production succeeds. | TCP `32960`, HTTP `20100` |
| JT808 ingest | `:jt808-ingest-app` | Accept JT/T 808 TCP connections on the production receive port, parse raw frames, archive frame bytes, and produce raw/event envelopes to Kafka. | TCP `808`, HTTP `20400` |
@@ -27,7 +27,7 @@ This runbook covers the default production runtimes: GB32960 ingest, JT808 inges
| `vehicle.dlq.mqtt-yutong.v1` | Kafka producer/consumer error paths | Operators/replay tooling | Dead-letter records for failed Yutong MQTT production or consumer processing. |
| `vehicle.dlq.history.v1` | History app consumer error paths | Operators/replay tooling | Dead-letter records for failed history storage processing. |
Default local consumer groups:
Default consumer groups:
- History: `vehicle-history`
- Analytics statistics: `vehicle-stat`
@@ -40,13 +40,13 @@ History and analytics failures do not block GB32960 ACKs. They are downstream Ka
Authorization failures are rejected before the Kafka durability boundary and can be ACKed/rejected immediately according to protocol handling.
## Local Prerequisites
## Build Prerequisites
- Java 25 and Maven available on PATH.
- Local Kafka reachable at `127.0.0.1:9092`, plus Kafka CLI tools such as `kafka-topics` and optionally `kafka-console-consumer`.
- Kafka CLI tools such as `kafka-topics` and optionally `kafka-console-consumer` available on the ECS/operator host.
- Session state requires Redis. GB32960/JT808 ingest services keep live Netty
channels in-process, but session indexes and TTL metadata use Redis only.
- No repository-local Kafka bootstrap script or compose file was found during Task 8 verification on 2026-06-23.
- Redis is configured through Portainer environment variables such as `REDIS_HOST` and `REDIS_DATABASE=50`; there is no memory session-store fallback.
If your shell needs an explicit JDK:
@@ -73,99 +73,50 @@ Expected result: `BUILD SUCCESS` and these runnable jars:
## Create Topics
Run these only after Kafka is reachable at `127.0.0.1:9092`:
Run these only on the ECS/operator host after Kafka is reachable. The default bootstrap address is the ECS private Kafka address used by the production stack:
```bash
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.raw.gb32960.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.event.gb32960.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.dlq.gb32960.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.raw.jt808.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.event.jt808.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.dlq.jt808.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.raw.mqtt-yutong.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.event.mqtt-yutong.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.dlq.mqtt-yutong.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server 127.0.0.1:9092 --create --if-not-exists --topic vehicle.dlq.history.v1 --partitions 3 --replication-factor 1
KAFKA_BOOTSTRAP="${KAFKA_BOOTSTRAP:-172.17.111.56:9092}"
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.raw.gb32960.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.event.gb32960.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.dlq.gb32960.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.raw.jt808.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.event.jt808.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.dlq.jt808.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.raw.mqtt-yutong.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.event.mqtt-yutong.v1 --partitions 12 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.dlq.mqtt-yutong.v1 --partitions 3 --replication-factor 1
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --create --if-not-exists --topic vehicle.dlq.history.v1 --partitions 3 --replication-factor 1
```
Optional sanity check:
```bash
kafka-topics --bootstrap-server 127.0.0.1:9092 --list | grep -E 'vehicle\.(raw|event|dlq)\.(gb32960|jt808|mqtt-yutong|history)\.v1'
kafka-topics --bootstrap-server "$KAFKA_BOOTSTRAP" --list | grep -E 'vehicle\.(raw|event|dlq)\.(gb32960|jt808|mqtt-yutong|history)\.v1'
```
## Start Split Services Locally
## Production Runtime
Run each command in a separate terminal from the repository root.
Production services run on ECS through Portainer/Docker. Do not start GB32960, JT808, Yutong MQTT, history, or analytics services on local developer machines; local machines are for code build, unit tests, and source inspection only.
GB32960 ingest:
Use `deploy/portainer/docker-compose.yml` as the production runtime manifest. The default stack is:
```bash
KAFKA_BROKERS=127.0.0.1:9092 \
REDIS_HOST=127.0.0.1 \
REDIS_PORT=6379 \
REDIS_DATABASE=50 \
GB32960_PORT=32960 \
HTTP_PORT=20100 \
java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/gb32960-ingest-app/target/gb32960-ingest-app.jar
```
- `gb32960-ingest-app`
- `jt808-ingest-app`
- `yutong-mqtt-app`
- `vehicle-history-app`
- `vehicle-analytics-app`
JT808 ingest:
`vehicle-history-app` intentionally has no raw archive volume. The history hot path is Kafka to TDengine: raw envelopes are stored in TDengine `raw_frames` with `parsedJson`, `metadataJson`, and `rawUri`. Ingest services may still write original `.bin` files as cold backup, but history API queries must not depend on a shared local archive mount.
```bash
KAFKA_BROKERS=127.0.0.1:9092 \
REDIS_HOST=127.0.0.1 \
REDIS_PORT=6379 \
REDIS_DATABASE=50 \
JT808_PORT=808 \
HTTP_PORT=20400 \
java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar
```
Yutong MQTT ingest:
```bash
KAFKA_BROKERS=127.0.0.1:9092 \
YUTONG_MQTT_ENABLED=true \
YUTONG_MQTT_URI='<mqtt-uri>' \
YUTONG_MQTT_USERNAME='<mqtt-user>' \
YUTONG_MQTT_PASSWORD='<mqtt-password>' \
HTTP_PORT=20500 \
java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/yutong-mqtt-app/target/yutong-mqtt-app.jar
```
Vehicle history:
```bash
KAFKA_BROKERS=127.0.0.1:9092 \
HTTP_PORT=20200 \
TDENGINE_HISTORY_ENABLED=true \
TDENGINE_HISTORY_DATABASE=vehicle_ts \
TDENGINE_JDBC_URL='jdbc:TAOS-WS://<tdengine-host>:6041/vehicle_ts' \
TDENGINE_USERNAME=root \
TDENGINE_PASSWORD='<tdengine-password>' \
java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/vehicle-history-app/target/vehicle-history-app.jar
```
`SINK_ARCHIVE_PATH` is intentionally omitted from the history JVM. The history hot path is Kafka to TDengine: raw envelopes are stored in TDengine `raw_frames` with `parsedJson`, `metadataJson`, and `rawUri`. Ingest services may still write original `.bin` files as cold backup, but history API queries must not depend on a shared local archive mount.
Vehicle analytics:
```bash
KAFKA_BROKERS=127.0.0.1:9092 \
HTTP_PORT=20300 \
java --sun-misc-unsafe-memory-access=allow \
-jar modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar
```
Keep `TDENGINE_HISTORY_ENABLED=true` in the `vehicle-history-app` environment so history reads and writes use TDengine in production.
`vehicle-analytics-app` is intentionally a metric runtime only. Latest-state APIs belong to `vehicle-state-service`, which stays outside the default reactor and should be built with `-Poptional-latest-state` and deployed as a separate consumer if that surface is needed.
## Health Verification
Run these from the ECS host or inside the matching container:
```bash
curl -sS http://127.0.0.1:20100/actuator/health
curl -sS http://127.0.0.1:20100/actuator/health/liveness
@@ -210,10 +161,10 @@ Expected: the ACK file is non-empty and the decoded bytes begin with the GB32960
Verify only what was actually run in your environment:
```bash
kafka-console-consumer --bootstrap-server 127.0.0.1:9092 --topic vehicle.raw.gb32960.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server 127.0.0.1:9092 --topic vehicle.event.gb32960.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server 127.0.0.1:9092 --topic vehicle.raw.mqtt-yutong.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server 127.0.0.1:9092 --topic vehicle.event.mqtt-yutong.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server "$KAFKA_BOOTSTRAP" --topic vehicle.raw.gb32960.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server "$KAFKA_BOOTSTRAP" --topic vehicle.event.gb32960.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server "$KAFKA_BOOTSTRAP" --topic vehicle.raw.mqtt-yutong.v1 --from-beginning --max-messages 1 --timeout-ms 10000
kafka-console-consumer --bootstrap-server "$KAFKA_BOOTSTRAP" --topic vehicle.event.mqtt-yutong.v1 --from-beginning --max-messages 1 --timeout-ms 10000
```
Use TDengine CLI or a JDBC client to verify history writes:
@@ -251,17 +202,15 @@ Do not expect `vehicle-history-app` to create raw `.bin` archive files from Kafk
Do not mark any of these as verified unless the matching command was run and the output was inspected.
## Local launchctl Deployment
## Runtime Location Policy
Use the templates under `deploy/local/launchctl/` for the local TCP-focused production-verification machine. They currently cover GB32960, JT808, and history; run Yutong MQTT separately with the command above or deploy it through Portainer.
Production services run on ECS through Portainer/Docker.
- GB32960 ingest: `com.lingniu.gb32960`, TCP `32960`, HTTP `20100`
- JT808 ingest: `com.lingniu.jt808`, TCP `808`, HTTP `20400`
- History: `com.lingniu.vehicle-history`, HTTP `20200`
- Do not create local service runners for GB32960, JT808, Yutong MQTT, history, or analytics.
- Do not run the service jars directly on developer machines for production verification.
- Keep local work limited to source edits, builds, and automated tests.
The launchctl history template does not inject `SINK_ARCHIVE_PATH`. Use TDengine `raw_frames` as the authoritative hot-query store; keep any ingest-side raw archive path as an optional cold backup for operator inspection.
For Portainer deployments, mirror this same shape: no history archive volume, history consumes raw/event Kafka topics and writes TDengine history rows.
For Portainer deployments, keep history without an archive volume: history consumes raw/event Kafka topics and writes TDengine history rows.
## Rollback Guidance
@@ -273,7 +222,7 @@ If the split deployment is unhealthy:
4. If Kafka itself is unavailable, stop `gb32960-ingest-app` or route GB32960 traffic to a previously verified release that preserves the Kafka durability boundary.
5. After rollback, compare Kafka consumer group lag and DLQ contents before resuming the split services.
Rollback commands depend on the deployment environment. For local testing, stop the active Java processes and restart the previous verified app jars or images.
Rollback commands depend on the deployment environment. For the default production stack, roll back the Portainer stack image version and let Docker restart the affected containers.
## Task 8 Verification Notes
@@ -285,19 +234,19 @@ Observed on 2026-06-23 in worktree `.worktrees/gb32960-service-split`:
- `kafka-topics`, `kafka-topics.sh`, `docker`, and `docker-compose` were not found on PATH.
- Kafka topic creation, service startup, health checks, Kafka record checks, archive checks, TDengine checks, stat output checks, and ACK observation were not run because the local Kafka prerequisite was absent.
## Latest Local Verification
## Latest Build Verification
Observed on 2026-06-23 in worktree `.worktrees/gb32960-service-split`:
- Targeted module tests: `mvn -pl :sink-kafka,:ingest-core,:protocol-gb32960,:event-history-service,:vehicle-state-service,:vehicle-stat-service test` ended with `BUILD SUCCESS`; Maven reported 55 protocol/sink/core tests, 30 event-history tests, 14 vehicle-state tests, and 19 vehicle-stat tests with 0 failures/errors/skips.
- Split app tests should cover the current active apps listed in the Service Roles section.
- Package verification should use the active-app package command from the Build section.
- Split app startup: not run in this verification pass because local Kafka was still absent.
- Kafka raw records: not verified; no local Kafka broker or Kafka CLI tools were available.
- Kafka event records: not verified; no local Kafka broker or Kafka CLI tools were available.
- Split app startup: not run in this verification pass because an ECS/Portainer runtime was outside that build-only check.
- Kafka raw records: not verified in that build-only check.
- Kafka event records: not verified in that build-only check.
- TDengine history rows: not verified; downstream services were not started without Kafka.
- Analytics output: not verified; downstream services were not started without Kafka.
- ACK behavior: not verified against a live broker in this pass. Unit tests cover the GB32960 ACK boundary and ordering, but an operator should still run the ACK capture command above in a Kafka-backed local or staging environment.
- ACK behavior: not verified against a live broker in this pass. Unit tests cover the GB32960 ACK boundary and ordering, but an operator should still run the ACK capture command above on ECS or staging.
## Remote Kafka Live Verification
@@ -313,15 +262,12 @@ Observed on 2026-06-23 with Kafka `114.55.58.251:9092`:
This verifies the live path `GB32960 TCP 32960 -> gb32960-ingest-app -> Kafka raw/event topics` against the remote Kafka broker. Downstream `vehicle-history-app` and `vehicle-analytics-app` were not started in this pass.
## 2026-06-29 Local Production-Path Verification
## 2026-06-29 Superseded Local Verification Record
Observed on 2026-06-29 in worktree `.worktrees/vehicle-ingest-redesign-phase1`:
Observed on 2026-06-29 in worktree `.worktrees/vehicle-ingest-redesign-phase1`. This record is retained only as historical evidence of parser/storage behavior; do not repeat it as a deployment procedure because production services now run on ECS through Portainer/Docker.
- `jt808-ingest-app` was running through launchctl on TCP `808` and HTTP `20400`; `curl -sS http://127.0.0.1:20400/actuator/health` returned top-level status `UP`.
- `gb32960-ingest-app` was running through launchctl on TCP `32960` and HTTP `20100`; `curl -sS http://127.0.0.1:20100/actuator/health` returned top-level status `UP`.
- `vehicle-history-app` was running through launchctl on HTTP `20200`; `curl -sS http://127.0.0.1:20200/actuator/health` returned top-level status `UP`.
- External JT808 traffic on TCP `808` was parsed and written through Kafka into TDengine. Direct TDengine checks showed more than `6000` JT808 `raw_frames` and more than `1900` JT808 `vehicle_locations`; current production history does not maintain a `telemetry_fields` table.
- A GB32960 synthetic realtime frame sent to TCP `32960` received a binary ACK beginning with `2323`. The same VIN `LTEST202606290001` was queryable from TDengine-backed history APIs with speed, mileage, longitude, and latitude fields.
- History raw and event Kafka consumption used separate bindings so raw-frame writes remained current while location/field event ingestion continued.
This verifies the local path `GB32960/JT808 TCP -> protocol app -> Kafka raw/event topics -> vehicle-history-app -> TDengine raw_frames/location tables -> Swagger/API query`.
The verified behavior was `GB32960/JT808 TCP -> protocol app -> Kafka raw/event topics -> vehicle-history-app -> TDengine raw_frames/location tables -> Swagger/API query`; the deployment method from that historical run is superseded.

View File

@@ -44,125 +44,51 @@ mvn -pl :gb32960-ingest-app,:jt808-ingest-app,:yutong-mqtt-app,:vehicle-history-
- `modules/apps/vehicle-history-app/target/vehicle-history-app.jar`
- `modules/apps/vehicle-analytics-app/target/vehicle-analytics-app.jar`
## 启动 JT808 接入服务,监听 808 端口
## ECS 服务状态验证
生产服务只在 ECS 上运行,通过 Portainer/Docker 管理。不要在本机用 `java -jar`、plist 或其它守护进程方式启动 GB32960、JT808、Yutong MQTT、history、analytics。
```bash
HTTP_PORT=20400 \
JT808_PORT=808 \
KAFKA_CONSUMER_ENABLED=false \
java -jar modules/apps/jt808-ingest-app/target/jt808-ingest-app.jar
```
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}' \
| egrep 'gb32960|jt808|yutong|vehicle-history|vehicle-analytics|NAMES'
验证:
ss -lntp | egrep ':(808|32960|20100|20200|20300|20400|20500)\b'
```bash
curl -sS http://127.0.0.1:20400/actuator/health
curl -sS http://127.0.0.1:20400/actuator/health/liveness
curl -sS http://127.0.0.1:20400/actuator/health/readiness
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
curl -sS http://127.0.0.1:20100/actuator/health/liveness
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
HTTP_PORT=20200 \
KAFKA_CONSUMER_ENABLED=true \
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/actuator/health/liveness
curl -sS http://127.0.0.1:20200/actuator/health/readiness
curl -sS http://127.0.0.1:20200/v3/api-docs \
| grep -E '/api/event-history/locations|/api/event-history/raw-frames'
```
预期:健康检查为 `UP`OpenAPI 中包含通用位置分页查询和 RAW 帧查询接口。history-app 不暴露 `/api/event-history/telemetry/fields`,也不持续写入逐字段宽表。
## 启动 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` 指标。
预期:五个容器均为运行状态;健康检查为 `UP`JT808/GB32960 TCP 端口在 ECS 上监听OpenAPI 中包含通用位置分页查询和 RAW 帧查询接口。history-app 不暴露 `/api/event-history/telemetry/fields`也不持续写入逐字段宽表。JT808 位置帧中有 GPS 总里程时,`vehicle-analytics-app` 按差值法写入 MySQL `vehicle_stat_metric``daily_mileage_km` 指标。
## 本机 launchctl 部署
## 运行位置约束
当前本机生产验证建议使用仓库模板生成 plist
```bash
deploy/local/launchctl/
```
关键约束:
生产身份绑定固定使用 MySQL不再提供 file/memory/sqlite 运行时切换入口。生产服务固定运行在 ECS/Portainer不提供本机守护进程模板。
- `jt808-ingest-app` 监听 TCP `808`HTTP `20400`
- `gb32960-ingest-app` 监听 TCP `32960`HTTP `20100`
- `yutong-mqtt-app` 监听 HTTP `20500`
- `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 拷贝中途重启。
- `vehicle-analytics-app` 监听 HTTP `20300`
- history 热查询只依赖 Kafka 和 TDengine `raw_frames`history 不需要共享 archive volume
- GB32960/JT808/Yutong MQTT 接入服务可以继续使用 `SINK_ARCHIVE_PATH` 保存原始冷备,但这不是 history API 的实时查询前置条件。
JT808 注册身份绑定:
- 生产身份绑定固定使用 MySQL不再提供 file/memory/sqlite 运行时切换入口。
- 生产需要把 0x0100 注册信息维护到 MySQL 时,只需要配置 `VEHICLE_IDENTITY_MYSQL_*` 连接参数。
- 需要提供 `VEHICLE_IDENTITY_MYSQL_JDBC_URL``VEHICLE_IDENTITY_MYSQL_USERNAME``VEHICLE_IDENTITY_MYSQL_PASSWORD`
- 服务启动时自动创建 `vehicle_identity_binding``vehicle_identity_binding_registration` 两张表。`vehicle_identity_binding` 只维护 `plate``vin` 两列;`vehicle_identity_binding_registration``protocol + phone` 保存 JT808 0x0100 注册字段。
@@ -220,7 +146,7 @@ API / Swagger
## JT808 实时转发验收
如果外部平台已经把 JT808 报文转发到本机 TCP `808`,至少观察 60 秒日志和 Kafka 数据。
如果外部平台已经把 JT808 报文转发到 ECS TCP `808`,至少观察 60 秒日志和 Kafka 数据。
必须拿到以下证据:
@@ -272,13 +198,15 @@ SELECT COUNT(*) FROM jt808_locations;
- TDengine 未启用时TDengine 专属接口不应该出现在 OpenAPI 中。
- 路径不存在时API 层应该返回 HTTP `404`,而不是泛化的存储失败。
## 2026-06-29 本机实时链路验证结果
## 2026-06-29 Superseded Local Live Verification Record
运行服务:
该记录仅保留为解析和存储行为的历史证据;生产运行位置已经收敛到 ECS/Portainer。
- `com.lingniu.jt808.808`: `jt808-ingest-app`TCP `808`HTTP `20400`
- `com.lingniu.gb32960.32960`: `gb32960-ingest-app`TCP `32960`HTTP `20100`
- `com.lingniu.vehicle-history.jt808`: `vehicle-history-app`HTTP `20200`
当时参与验证的服务:
- `jt808-ingest-app`TCP `808`HTTP `20400`
- `gb32960-ingest-app`TCP `32960`HTTP `20100`
- `vehicle-history-app`HTTP `20200`
当次健康检查均返回 `{"status":"UP"}`
@@ -300,7 +228,7 @@ python3 tools/vehicle_ingest_live_verify.py \
JT808 真实转发链路已验证:
- 本机 TCP `808` 有外部平台 `222.66.200.68` 持续发送 JT808 报文。
- ECS TCP `808` 有外部平台 `222.66.200.68` 持续发送 JT808 报文。
- `vehicle.raw.jt808.v1``vehicle.event.jt808.v1` 被 history 消费。
- `raw_frames``protocol='JT808'` 的真实行数已超过 `36000`
- 外部平台真实 0x0100 注册帧已超过 `347` 条,真实 0x0200 位置帧已超过 `12400` 条。
@@ -309,7 +237,7 @@ JT808 真实转发链路已验证:
- 分页 API 已用终端号 `13079963301` 验证第一页和 nextCursor 第二页,样例位置包含 `longitude=118.913846``latitude=31.927309``statusFlag=3``archive://2026/06/29/JT808/...` 原始帧引用。
- 注册帧样例:终端号 `13079963320`、deviceId `9963320`、deviceType `SEG-9888G`、plate `沪A61559F`、maker `70112`、province `31`、city `113`、plateColor `2`。生产 VIN 反写依赖 MySQL identity store后续 raw/event 的 VIN 解析也从 MySQL 绑定读取。
## JT808 本机 smoke / 轻压测工具
## JT808 ECS smoke / 轻压测工具
仓库提供 `tools/jt808_e2e_smoke.py`,用于重复验证 TCP `808` 到 TDengine history 的闭环:
@@ -416,7 +344,7 @@ curl -sS 'http://127.0.0.1:20200/api/event-history/gb32960/snapshots/fields?vin=
## 当前注意事项
- 当前本机使用 TDengine WebSocket JDBC例如 `jdbc:TAOS-WS://<tdengine-host>:6041/vehicle_ts`
- 当前生产链路使用 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>`;启用 MySQL identity store 后registration 表中已反写 VIN 的 phone/deviceId/plate 会用于后续 raw/event 的 VIN 解析。