Files
lingniu-vehicle-ingest/docs/ops/100k-capacity-baseline.md
2026-07-03 18:58:37 +08:00

161 lines
8.1 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.
# 100K 车辆接入容量基线
更新时间2026-07-03
## 目标
支撑 100,000 台车辆接入,入口服务在高连接数和高帧率下保持可观测、可背压、可恢复。
## 初始容量假设
| 项 | 目标 |
| --- | --- |
| 连接车辆数 | 100,000 |
| 平均帧间隔 | 10-30 秒 |
| 平均入口 FPS | 3,000-10,000 |
| 短时 burst FPS | 20,000 |
| Gateway p99 parse + enqueue | < 50ms |
| Redis 当前态延迟 | < 3s |
| TDengine 历史写入 lag | 可观测且 burst 后下降 |
| MySQL 当前态 | 异步,不能阻塞 Redis |
## 当前生产观测
当前 ECS `115.29.187.205` 在低负载下健康:
- JT808 连接约 242。
- GB32960 连接约 2。
- Kafka lag 为 0。
- NATS ack pending 为 0。
- Redis 写入约 0ms。
- MySQL 投影约 1-2ms。
- ECS load 约 `0.09 / 0.15 / 0.21`
- 可用内存约 6.6GB。
- 根分区使用约 37%。
## 当前已知缺口
- `net.core.somaxconn=128`,无法作为 100K 连接生产基线。
- Gateway 默认 `TCP_MAX_CONNECTIONS` 已调整为 `120000`,生产仍可通过环境变量覆盖。
- 已新增可重复的 TCP 连接压测工具,后续需要用它跑 10K/50K/100K 阶段测试并记录结果。
- 仍缺读超时按协议维度计数Gateway frame duration 已提供 histogram可用于 parse + enqueue + response 的 p95/p99 估算。
- TDengine history writer 当前逐消息插入,后续需要批量写入。
- Kafka topic 当前 12 分区100K 目标下需要结合实际 FPS 再评估分区数。
## ECS OS 参数建议
100K 连接目标需要至少以下系统参数作为起点:
```bash
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535
sysctl -w net.ipv4.ip_local_port_range="10000 65000"
sysctl -w net.ipv4.tcp_tw_reuse=1
```
systemd gateway 已配置 `LimitNOFILE=1048576`,需要持续保持。
## 验收指标
| 层 | 指标 | 目标 |
| --- | --- | --- |
| Gateway | `vehicle_gateway_active_connections` | 能稳定到阶段目标连接数 |
| Gateway | `vehicle_gateway_connection_rejections_total` | 容量目标内不增长 |
| Gateway async sink | `vehicle_async_sink_queue_depth{sink}` | 队列深度不持续增长 |
| Gateway async sink | `vehicle_async_sink_enqueue_total{sink,kind,status}` | `timeout/closed` 不增长 |
| Gateway async sink | `vehicle_async_sink_publish_total{sink,kind,status}` | `error` 不增长 |
| Gateway | `vehicle_gateway_publish_total{status="ok"}` | 持续增长 |
| Gateway | `vehicle_gateway_frame_duration_ms_histogram_bucket` | p99 小于容量目标 |
| History writer | `vehicle_history_batch_flush_total{status}` | `error` 不增长 |
| History writer | `vehicle_history_batch_rows_total{status}` | batch 行数持续增长 |
| History writer | `vehicle_history_batch_pending_messages` | 稳态接近 0burst 后下降 |
| History writer | `vehicle_history_batch_pending_rows` | 稳态接近 0burst 后下降 |
| History writer | `vehicle_history_batch_flush_duration_ms{status}` | flush 延迟不持续上升 |
| NATS bridge | `vehicle_bridge_nats_consumer_ack_pending` | 稳态为 0 |
| NATS bridge | `vehicle_bridge_nats_consumer_pending` | burst 后下降 |
| NATS bridge | `vehicle_bridge_batch_pending_messages` | 稳态接近 0burst 后下降 |
| NATS bridge | `vehicle_bridge_batch_duration_ms_histogram_bucket` | p99 不持续上升 |
| Kafka consumers | `vehicle_*_kafka_lag` | 稳态为 0burst 后下降 |
| Realtime Redis | `vehicle_realtime_store_update_duration_ms{store="redis"}` | 毫秒级 |
| Realtime MySQL | async queue depth | 不持续增长 |
## 分阶段压测
压测入口:
```bash
# 100 连接 smoke test
/opt/lingniu-go-native/current/load-sim \
-protocol jt808 \
-addr 127.0.0.1:808 \
-connections 100 \
-connect-rate 100 \
-send-interval 10s \
-duration 2m \
-template 0200 \
-send=false
```
`load-sim``-send=true` 时会按连接和帧序号生成可被现有解析器解析的唯一协议帧:
- JT808 会变更包头手机号、流水号和 `0x0200` 位置时间,并重新计算转义和校验码。
- GB32960 会变更 VIN 和实时数据时间,并重新计算 BCC。
- 低 FPS 全链路压测必须使用该模式,避免重复静态帧导致 event id 冲突。
- 对生产端口执行 `-send=true` 会写入合成 raw 数据,只能在明确隔离标识和压测窗口后执行。
1. 100 连接 smoke test。
2. 10,000 连接保持测试。
3. 10,000 连接 + 1 FPS/连接短测。
4. 50,000 连接保持测试。
5. 100,000 连接保持测试。
6. 按真实协议分布进行混合帧率测试。
每一阶段必须记录:
- active connections
- gateway frame/publish counters
- NATS pending 和 ack pending
- Kafka lag
- Redis/MySQL/TDengine 写入耗时和 pending depth
- CPU/load/memory/file descriptors
- 错误日志
## 2026-07-03 阶段压测记录
压测方式:在 ECS 本机使用 `/opt/lingniu-go-native/current/load-sim``127.0.0.1:808` 发起 JT808 hold-only 连接,`-send=false`,不发送业务帧,不污染 raw 数据。
压测前基线,时间 `2026-07-03 18:03:10 CST`
| 项 | 值 |
| --- | --- |
| 服务状态 | 6 个 Go systemd 服务均 active |
| JT808 连接 | 约 240 |
| GB32960 连接 | 约 2 |
| load average | `0.43 / 0.22 / 0.23` |
| available memory | 约 `6661 MB` |
| NATS ack pending | `0` |
| NATS pending | 约 `39` |
| history/stat/realtime Kafka lag | `0` |
阶段结果:
| 阶段 | 时间 | 参数 | 峰值连接/FD | 结果 | 资源和队列 |
| --- | --- | --- | --- | --- | --- |
| 100 连接 | `18:03:21-18:04:21 CST` | `connections=100 connect-rate=100 duration=60s send=false` | JT808 active `340``ss``341` | opened `100`failed `0`frames `0`write_errors `0` | load 约 `0.33/0.21/0.22`available memory 约 `6659 MB` |
| 1,000 连接 | `18:04:38-18:05:38 CST` | `connections=1000 connect-rate=500 duration=60s send=false` | JT808 active `1240``ss``1241`gateway FD 约 `1256` | opened `1000`failed `0`frames `0`write_errors `0` | load 约 `0.80/0.33/0.26`available memory 约 `6645 MB` |
| 10,000 连接 | `18:05:59-18:07:59 CST` | `connections=10000 connect-rate=1000 duration=120s send=false` | JT808 active `10240``ss``10241`gateway FD 约 `10256` | opened `10000`failed `0`frames `0`write_errors `0` | 20 秒时 load 约 `0.45/0.33/0.27`available memory 约 `6409 MB`NATS ack pending `0` |
| 50,000 连接 | `18:11:22-18:14:22 CST` | `connections=50000 connect-rate=2000 duration=180s send=false` | JT808 active `50238``ss``50239`gateway FD 约 `50254` | opened `50000`failed `0`frames `0`write_errors `0` | 45 秒时 load 约 `0.07/0.23/0.24`available memory 约 `5590 MB`NATS ack pending 短时 `29`,后续归零 |
| 100,000 总连接 | `18:18:13-18:21:13 CST` | JT808 `50000` + GB32960 `50000`,各 `connect-rate=2000 duration=180s send=false` | JT808 active `50236`GB32960 active `50002`,总 active 约 `100238`gateway FD 约 `100252` | JT808 opened `50000` / failed `0`GB32960 opened `50000` / failed `0`frames `0`write_errors `0` | 75 秒时 load 约 `0.16/0.30/0.29`available memory 约 `4511 MB`NATS ack pending 短时 `10`,后续归零 |
压测后:
- `2026-07-03 18:08:47 CST` JT808 active 回落到 `240``ss``241`
- `2026-07-03 18:15:36 CST` 5W 压测后 JT808 active 回落到约 `238``ss``239`
- `2026-07-03 18:16:49 CST` NATS ack pending 回到 `0`history/stat/realtime Kafka lag 总和均为 `0`
- `2026-07-03 18:23:02 CST` 10W 总连接压测后 JT808 active 回落到 `236`GB32960 active 回落到 `2`NATS ack pending 为 `0`history/stat/realtime Kafka lag 总和均为 `0`
- `20211/20212/20213/20214/20200` readyz 均 OK。
- 压测窗口未出现 gateway `error|failed|panic|fatal|rejected` 日志。
- `vehicle_gateway_connection_rejections_total` 未输出,表示本轮没有连接拒绝计数。
结论:单 ECS 已通过本机 10W 总连接 hold-only 基线测试。该结果证明当前内核参数、gateway 连接上限和 systemd 文件句柄设置可以承载 10W 空闲长连接;下一阶段必须进入带真实帧率的低 FPS 压测验证解析、NATS、Kafka、Redis、TDengine、MySQL 全链路吞吐。