8.1 KiB
车辆接入生产运行手册
范围
本文覆盖 ECS 115.29.187.205 上的 Go 原生车辆接入链路:
- GB32960 TCP 接入
- JT/T 808 TCP 接入
- 宇通 MQTT 接入
- NATS 到 Kafka 桥接
- Kafka 历史、统计、实时消费者
- Redis 实时缓存、MySQL 实时表、TDengine 历史表
运行手册的目标是按自上而下的顺序定位问题:入口、队列、桥接、消费、存储、查询 API。
当前生产服务、topic、表和 Redis key 的清单见 生产数据面清单。
服务地图
| 层级 | 服务 | systemd 单元 | 本机端点 |
|---|---|---|---|
| 接入 | Gateway | lingniu-go-gateway.service |
127.0.0.1:20211 |
| 桥接 | NATS Kafka bridge | lingniu-go-nats-kafka-bridge.service |
127.0.0.1:20214 |
| 历史 | TDengine writer | lingniu-go-history-writer.service |
127.0.0.1:20212 |
| 统计 | MySQL stat writer | lingniu-go-stat-writer.service |
127.0.0.1:20213 |
| 实时 | Realtime API/projector | lingniu-go-realtime-api.service |
127.0.0.1:20200 |
Topic 配置基线
生产环境的 env 文件必须和 Go topic 命名空间保持一致:
| 服务 | 必要 topic |
|---|---|
lingniu-go-history-writer.service |
vehicle.raw.go.gb32960.v1、vehicle.raw.go.jt808.v1、vehicle.raw.go.yutong-mqtt.v1 |
lingniu-go-stat-writer.service |
vehicle.raw.go.gb32960.v1、vehicle.raw.go.jt808.v1、vehicle.raw.go.yutong-mqtt.v1 |
lingniu-go-realtime-api.service |
vehicle.raw.go.gb32960.v1、vehicle.raw.go.jt808.v1、vehicle.raw.go.yutong-mqtt.v1 |
lingniu-go-nats-kafka-bridge.service |
NATS raw subjects 到同名 Kafka topic;vehicle.event.go.unified.v1 只在兼容开关打开时使用 |
如果 stat-writer 少消费某个 raw topic,对应协议的每日里程不会进入 vehicle_daily_mileage。修正后可能出现短时间 Kafka lag,这是在追补历史 backlog;只要 vehicle_stat_writes_total 持续增长且 lag 下降,就是健康状态。
Realtime API 是当前态投影,默认在没有已提交 offset 时从 latest 开始消费。切换 topic 或新建 consumer group 后,不应让 realtime 追扫历史 raw backlog;需要重建当前态时,应使用明确的回放任务或手动 reset offset。
业务端口:
- GB32960 TCP:
0.0.0.0:32960 - JT/T 808 TCP:
0.0.0.0:808 - 实时/API:
0.0.0.0:20200
五分钟排查顺序
先回答最核心的问题:数据有没有进来,有没有排队,有没有被消费,最后有没有被查询到。
- 检查所有服务
/readyz。 - 检查 gateway 帧计数和 TCP 活跃连接。
- 检查 NATS bridge 的 pending 和 ack-pending。
- 检查 bridge 写 Kafka 与 NATS ack 是否同时增长。
- 检查 history、stat、realtime 三类 Kafka consumer lag。
- 检查各 writer 的写入、提交、更新计数。
- 最后再查存储和业务查询 API。
for port in 20211 20212 20213 20214 20200; do
curl -fsS "http://127.0.0.1:${port}/readyz"
echo
done
curl -fsS http://127.0.0.1:20211/metrics \
| grep -E 'vehicle_gateway_(active_connections|frames_total|publish_total)'
curl -fsS http://127.0.0.1:20214/metrics \
| grep -E 'vehicle_bridge_(nats_consumer|kafka_writes_total|nats_acks_total)'
curl -fsS http://127.0.0.1:20212/metrics | grep vehicle_history_kafka_lag
curl -fsS http://127.0.0.1:20213/metrics | grep vehicle_stat_kafka_lag
curl -fsS http://127.0.0.1:20200/metrics | grep vehicle_realtime_kafka_lag
健康基线
当前生产环境的健康特征:
- 所有
/readyz都返回status=ok。 vehicle_bridge_nats_consumer_ack_pending为0。- history、stat、realtime 的 Kafka lag 为
0或短时间小幅波动后归零。 - gateway 的帧计数持续增长。
- bridge 的 Kafka write 和 NATS ack 计数同时增长。
- writer 的成功计数增长,同时 Kafka lag 不持续扩大。
GB32960 和 JT/T 808 的活跃连接数受上游平台连接方式影响,不能直接等同于车辆数。突然归零或持续异常下降才是信号。
告警阈值建议
| 信号 | 建议阈值 | 含义 |
|---|---|---|
/readyz 非 ok |
立即处理 | 服务或依赖不可用。 |
| Gateway 活跃连接 | 预期有流量时某协议降为 0 |
上游网络、监听端口或进程可能异常。 |
vehicle_gateway_frames_total{status!="OK"} |
连续 2 分钟增长 | 解析器或上游报文质量异常。 |
vehicle_bridge_nats_consumer_ack_pending |
连续 2 分钟 > 0 |
消息已投递给 bridge,但 Kafka 写入后未完成 ack。 |
vehicle_bridge_nats_consumer_pending |
持续增长且 > 10000 |
bridge 消费 NATS 的速度跟不上生产速度。 |
| Kafka lag | 连续 5 分钟增长或 > 10000 |
下游 consumer 或存储存在瓶颈。 |
| Writer 成功计数 | 入口增长但 writer 不增长 | bridge、Kafka、consumer 或存储链路断开。 |
事故处理路径
没有新数据
- 先确认监听端口。
ss -lntp | grep -E ':(808|32960|20200|20211|20212|20213|20214) '
- 检查 gateway readiness 和日志。
curl -fsS http://127.0.0.1:20211/readyz
journalctl -u lingniu-go-gateway.service --since '10 minutes ago' --no-pager
- 看 gateway 帧计数是否增长。
- 如果 gateway 有增长但 bridge 没增长,查 NATS publish 和 bridge 日志。
- 如果 bridge 写入增长但 writer 不增长,查 Kafka lag 和 consumer 日志。
Kafka lag 持续增长
- 先从 metrics 定位是哪个服务、哪个 topic、哪个 partition。
- 检查对应服务
/readyz。 - 检查存储依赖:history 看 TDengine,stat 看 MySQL,realtime 看 Redis/MySQL/TDengine。
- 先看日志,再决定是否重启。
journalctl -u lingniu-go-history-writer.service --since '10 minutes ago' --no-pager
journalctl -u lingniu-go-stat-writer.service --since '10 minutes ago' --no-pager
journalctl -u lingniu-go-realtime-api.service --since '10 minutes ago' --no-pager
Kafka 是可回放日志。只要 Kafka 还保留消息,恢复 consumer 后 lag 应该能自动追平。不要在 lag 未归零前手工补数。
NATS pending 持续增长
- 检查 bridge
/readyz和日志。 - 对比
vehicle_bridge_kafka_writes_total和vehicle_bridge_nats_acks_total。 - 如果 Kafka 写入失败,检查 ECS 到 Kafka broker 的网络。
- 如果 ack-pending 卡住且日志持续报错,只重启 bridge。
journalctl -u lingniu-go-nats-kafka-bridge.service --since '10 minutes ago' --no-pager
systemctl restart lingniu-go-nats-kafka-bridge.service
Raw 有数据但实时查不到
- 查 realtime Kafka lag。
- 查 realtime update 计数。
- 查 realtime API readiness。
- 查最新 snapshot/location API。
curl -fsS http://127.0.0.1:20200/readyz
curl -fsS 'http://127.0.0.1:20200/api/realtime/locations?limit=1'
curl -fsS 'http://127.0.0.1:20200/api/realtime/snapshots?limit=1'
重启顺序
优先重启最小故障层:
- 只有一个 consumer lag 异常时,先重启对应 writer。
- 实时投影或 API 异常时,重启 realtime API。
- bridge pending 或 ack-pending 卡住时,重启 NATS Kafka bridge。
- 只有入口监听、解析循环或上游连接处理异常时,才重启 gateway。
systemctl restart lingniu-go-history-writer.service
systemctl restart lingniu-go-stat-writer.service
systemctl restart lingniu-go-realtime-api.service
systemctl restart lingniu-go-nats-kafka-bridge.service
systemctl restart lingniu-go-gateway.service
排查前不要直接全量重启。全量重启会抹掉时间线证据,也会掩盖问题到底发生在入口、队列、存储还是查询层。
存储原则
运行指标保留在 /metrics,不要为了服务健康计数新增 MySQL 或 TDengine 业务表。
业务存储保持最小化:
- raw frames 保存完整 parsed JSON,用于回放和审计。
- realtime snapshot/location 只保存 API 需要的当前业务字段。
- history 表保存可查询的时间序列核心字段。
- 派生统计应能从 Kafka 或 raw history 重新计算。
只有当产品查询明确需要、并且指标定义稳定时,才新增持久化聚合。