chore: remove local service runners
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user