Files
lingniu-vehicle-ingest/docs/ops/vehicle-ingest-runbook.md
2026-07-02 19:32:52 +08:00

178 lines
6.7 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.
# 车辆接入生产运行手册
## 范围
本文覆盖 ECS `115.29.187.205` 上的 Go 原生车辆接入链路:
- GB32960 TCP 接入
- JT/T 808 TCP 接入
- 宇通 MQTT 接入
- NATS 到 Kafka 桥接
- Kafka 历史、统计、实时消费者
- Redis 实时缓存、MySQL 实时表、TDengine 历史表
运行手册的目标是按自上而下的顺序定位问题:入口、队列、桥接、消费、存储、查询 API。
## 服务地图
| 层级 | 服务 | 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` |
业务端口:
- GB32960 TCP`0.0.0.0:32960`
- JT/T 808 TCP`0.0.0.0:808`
- 实时/API`0.0.0.0:20200`
## 五分钟排查顺序
先回答最核心的问题:数据有没有进来,有没有排队,有没有被消费,最后有没有被查询到。
1. 检查所有服务 `/readyz`
2. 检查 gateway 帧计数和 TCP 活跃连接。
3. 检查 NATS bridge 的 pending 和 ack-pending。
4. 检查 bridge 写 Kafka 与 NATS ack 是否同时增长。
5. 检查 history、stat、realtime 三类 Kafka consumer lag。
6. 检查各 writer 的写入、提交、更新计数。
7. 最后再查存储和业务查询 API。
```bash
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 或存储链路断开。 |
## 事故处理路径
### 没有新数据
1. 先确认监听端口。
```bash
ss -lntp | grep -E ':(808|32960|20200|20211|20212|20213|20214) '
```
2. 检查 gateway readiness 和日志。
```bash
curl -fsS http://127.0.0.1:20211/readyz
journalctl -u lingniu-go-gateway.service --since '10 minutes ago' --no-pager
```
3. 看 gateway 帧计数是否增长。
4. 如果 gateway 有增长但 bridge 没增长,查 NATS publish 和 bridge 日志。
5. 如果 bridge 写入增长但 writer 不增长,查 Kafka lag 和 consumer 日志。
### Kafka lag 持续增长
1. 先从 metrics 定位是哪个服务、哪个 topic、哪个 partition。
2. 检查对应服务 `/readyz`
3. 检查存储依赖history 看 TDenginestat 看 MySQLrealtime 看 Redis/MySQL/TDengine。
4. 先看日志,再决定是否重启。
```bash
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 持续增长
1. 检查 bridge `/readyz` 和日志。
2. 对比 `vehicle_bridge_kafka_writes_total``vehicle_bridge_nats_acks_total`
3. 如果 Kafka 写入失败,检查 ECS 到 Kafka broker 的网络。
4. 如果 ack-pending 卡住且日志持续报错,只重启 bridge。
```bash
journalctl -u lingniu-go-nats-kafka-bridge.service --since '10 minutes ago' --no-pager
systemctl restart lingniu-go-nats-kafka-bridge.service
```
### Raw 有数据但实时查不到
1. 查 realtime Kafka lag。
2. 查 realtime update 计数。
3. 查 realtime API readiness。
4. 查最新 snapshot/location API。
```bash
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'
```
## 重启顺序
优先重启最小故障层:
1. 只有一个 consumer lag 异常时,先重启对应 writer。
2. 实时投影或 API 异常时,重启 realtime API。
3. bridge pending 或 ack-pending 卡住时,重启 NATS Kafka bridge。
4. 只有入口监听、解析循环或上游连接处理异常时,才重启 gateway。
```bash
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 重新计算。
只有当产品查询明确需要、并且指标定义稳定时,才新增持久化聚合。