Skip to content

压测 ​

tools/loadtest 是一个独立的 Go 模块,模拟很多用户同时连上一个 Talkwire 服务端:登录、两两组成单聊、按人数分群,再以固定速率发消息,测量登录耗时、pub 应答耗时、单聊与群消息的送达耗时,并统计丢失。它的依赖与 tools/conformance 相同,只有 gorilla/websocket 与 golang-jwt。

工具目前只在本机试跑过,正式压测还没做,见文末 现状。

运行 ​

压测端需要服务端的 JWT_SECRET,用它给每个模拟用户签登录令牌。tools/loadtest/README.md 里的示例:

bash
cd tools/loadtest
LOADTEST_JWT_SECRET=<服务端的 JWT_SECRET> go run . -url ws://127.0.0.1:6062/ws/im -users 1000 -group-size 50 -rate 1 -duration 60s

LOADTEST_JWT_SECRET 少于 32 个字符时工具直接退出;-users 小于 2 或 -rate 不大于 0 时也直接退出。

参数 ​

下表来自 tools/loadtest/main.go 的命令行定义。

参数默认作用
-urlws://127.0.0.1:6062/ws/im服务端的 WebSocket 地址
-users100用户数,每人一条连接
-group-size10每个群的人数;小于 2 时不建群。用户同时两两配对发单聊
-rate1每人每秒发几条,单聊与群轮流
-duration30s发多久
-ramp10s连接在这段时间里均匀建立
-drain10s停发之后最多再等多久收尾
-timeout15s连接、登录和建群各自的超时
-prefix每次运行新生成用户 id 前缀
-max-loss0丢失超过这个比例就以 1 退出
-json不写另把结果写成 JSON 文件
-strict-tokentrue签 strict 档要求的令牌(type=access、role=app_user);对 legacy 档也能用

不给 -prefix 时每次运行生成一个新前缀(lt 加 8 位十六进制再加 -),几次运行之间互不看到对方的历史。

一次运行做什么 ​

一次运行分四步,前一步全部完成才进入下一步:

  1. 连接与登录:在 -ramp 内均匀地建立连接,每条连接发 login。令牌有效期 2 小时。
  2. 配对与建群:在线用户两两配对;每 -group-size 个人由第一个人发 create_grp 建一个群,建完等 1 秒让成员收到 grp_sync 完成订阅。
  3. 发送:每人按 -rate 定速发 pub,在单聊对象与群之间轮流,持续 -duration。
  4. 收尾:停发后最多再等 -drain,直到每条消息都有应答、该送达的都已收到,然后关闭连接。

消息正文带着发送时刻(lt|<Unix 纳秒>|…),接收方据此算送达耗时。所以多台压测机的时钟要同步,或者都在同一台机器上。

测量什么 ​

报告打印到标准输出;给了 -json 时另写一份 JSON。

项目含义
在线登录成功的用户数,以及连接失败、登录失败的个数和建立连接用的总秒数
群建成的群数与失败数
发送发出的消息数与每秒条数;写失败数;被服务端拒绝的条数(按应答码分);没等到应答的条数
送达应收与实收的送达次数、每秒送达数、丢失数。一条群消息对群里每个其他成员各算一次送达
closed early压测期间被服务端断开的连接数
耗时登录(从连接到登录应答)、应答(pub 到它的应答)、单聊送达、群送达,各给出条数与 p50、p95、p99、最大值,单位毫秒
错误不同的错误信息最多记 20 种,各带出现次数

被服务端拒绝的消息不计入应收送达。服务端发现某个连接的发送队列满了(客户端读得太慢)会断开它,这在报告里算 closed early,被断开的连接收不到的消息算丢失。

通过条件 ​

全部用户登录成功、全部群建成、每条消息都有应答、没有连接被中途断开,并且丢失比例不超过 -max-loss 时,工具以 0 退出,否则以 1 退出。一次送达都没有的运行也算失败;参数错误以 2 退出。

服务端怎么配 ​

压测要求所有用户互为好友、发送频率不被限流,tools/loadtest/README.md 给出的配法如下:

  • 宿主用 standalone 模式(TALKWIRE_HOST_MODE=standalone)的默认 allow-all,见 standalone 宿主。

  • 运行配置里的发送频率默认每人 10 秒 20 条,-rate 超过 2 时要调高;建大群时把人数上限调到 -group-size 以上。standalone 宿主的配置文件:

    json
    {"relations": "allow-all", "runtimeConfig": {"publishRateLimitPer10s": 100000, "maxMembers": 500, "readReceiptEnabled": true}}
  • 数据库用一个可以随便写的库:每条消息都入库。

这份配置写了 runtimeConfig 却没写 fcmEnabled,离线推送因此是关着的(没写的布尔项为 false)。压测不需要推送,照抄到别的部署时要补上 "fcmEnabled": true。

现状 ​

工具已经在本机试跑过,结果只说明工具能用、服务端在这个量级下行为正确,不代表服务端的上限。正式压测还没有做,计划在 Linux 上进行(README.md 的“当前状态”)。

本机试跑(2026-10-25) ​

环境是 Windows 11、i7-8700(12 个逻辑核)、16 GB;服务端、PostgreSQL 17 与压测端在同一台机器上,strict 档,standalone 宿主。压测端与服务端抢 CPU,网络是本机回环。

用户群每人每秒发送送达丢失ack p50 / p99群送达 p50 / p99
505 个 × 10 人14512 25103.2 / 13.1 ms2.6 / 10.7 ms
100020 个 × 50 人129 003(967/s)725 051(24 165/s)02.1 / 2.9 ms1.6 / 2.7 ms
10004 个 × 250 人118 608(863/s)2 315 748(107 349/s)7 017(0.3%)1 034 / 6 537 ms1 007 / 6 464 ms

最后一行已经饱和:每秒约 500 条群消息,每条发给 249 人。第一次跑这一档时压测端把每帧解码成通用的 map,自己先跟不上,服务端因此断开了 303 个读得慢的连接、丢了 25%;改成只解码需要的字段后,断开降到 7 个、丢失降到 0.3%。剩下的饱和是服务端的还是压测端的,在同一台机器上分不出来。

正式压测(待做) ​

正式压测要在 Linux 上做:服务端、数据库、压测端分开机器,压测端可以多台各跑一部分用户(各用不同的 -prefix)。同时记录服务端的 CPU、内存、goroutine 数和数据库的写入速率,逐步加大群的人数与速率,找到送达耗时开始上升、开始断开慢连接的那一档。

核心以 Apache-2.0 发布;端到端加密模块为 AGPLv3。