178 lines
6.7 KiB
Markdown
178 lines
6.7 KiB
Markdown
# 车辆接入生产运行手册
|
||
|
||
## 范围
|
||
|
||
本文覆盖 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 看 TDengine,stat 看 MySQL,realtime 看 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 重新计算。
|
||
|
||
只有当产品查询明确需要、并且指标定义稳定时,才新增持久化聚合。
|