# 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 async sink | `vehicle_async_sink_publish_duration_ms_histogram_bucket` | p99 不持续上升 | | 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` | 稳态接近 0,burst 后下降 | | History writer | `vehicle_history_batch_pending_rows` | 稳态接近 0,burst 后下降 | | 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` | 稳态接近 0,burst 后下降 | | NATS bridge | `vehicle_bridge_batch_duration_ms_histogram_bucket` | p99 不持续上升 | | Kafka consumers | `vehicle_*_kafka_lag` | 稳态为 0,burst 后下降 | | 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 全链路吞吐。