fix: 压测客户端改为 MQTT 5 并完成 hello 与收发统计

This commit is contained in:
Nixevol
2026-09-30 16:24:31 +08:00
parent 09fb544b7d
commit c72d1f0427
11 changed files with 1398 additions and 259 deletions
+61 -19
View File
@@ -11,30 +11,72 @@ import (
"git.asio.asia/nixevol/NixMsg/test/load"
)
// 压测客户端骨架:连上 N 个 MQTT 连接并打印连接数。完整 1000 连接 / 10 分钟压测留给 Q3。
func main() {
addr := flag.String("addr", "", "MQTT broker host:port(必填,不要写死业务端口)")
n := flag.Int("n", 10, "连接数")
prefix := flag.String("prefix", "q-bench-", "client id 前缀")
hold := flag.Duration("hold", 3*time.Second, "保持连接时长")
httpBase := flag.String("http", "", "服务 HTTP 根(WebSocket /mqtt 与管理/注册接口),如 http://127.0.0.1:12345")
adminHTTP := flag.String("admin-http", "", "管理接口根;默认与 -http 相同")
tcp := flag.String("tcp", "", "裸 MQTT TCP host:port;非空则 MQTT 走 TCP,HTTP 仍用于开通端")
n := flag.Int("n", 50, "在线连接数")
rate := flag.Float64("rate", 20, "单聊提交每秒条数")
duration := flag.Duration("duration", time.Minute, "单聊持续时长;0 表示跳过单聊")
hold := flag.Duration("hold", 0, "连上后先保持这么久再跑收发")
groupSize := flag.Int("group-size", -1, "群发成员数;默认与 -n 相同,0 表示跳过群发")
prefix := flag.String("prefix", "qb", "端编号前缀(小写)")
password := flag.String("password", "password1234", "端登录密码")
adminUser := flag.String("admin-user", "admin", "管理员用户名")
adminPass := flag.String("admin-pass", "", "管理员密码(批量开通)")
adminToken := flag.String("admin-token", "", "管理 API 令牌,与密码二选一")
regCode := flag.String("register-code", "", "自助注册安全码(不走管理开通时使用)")
reuse := flag.Bool("reuse", false, "编号已存在则跳过开通/注册")
scenario := flag.String("scenario", "all", "hold | dm | group | all")
flag.Parse()
if *addr == "" {
fmt.Fprintln(os.Stderr, "usage: mqttbench -addr host:port [-n 10]")
if *httpBase == "" && *tcp == "" {
fmt.Fprintln(os.Stderr, "usage: mqttbench -http http://host:port [options]")
flag.PrintDefaults()
os.Exit(2)
}
gs := *groupSize
if gs < 0 {
gs = *n
}
b := &load.MQTTBench{Addr: *addr, ClientIDPrefix: *prefix, Timeout: 5 * time.Second}
defer b.Close()
if err := b.ConnectN(*n, os.Stdout); err != nil {
fmt.Fprintln(os.Stderr, err)
cfg := load.Config{
HTTPBase: *httpBase,
AdminHTTP: *adminHTTP,
TCPAddr: *tcp,
AdminUser: *adminUser,
AdminPass: *adminPass,
APIToken: *adminToken,
RegisterCode: *regCode,
Reuse: *reuse,
Password: *password,
Prefix: *prefix,
N: *n,
Rate: *rate,
Duration: *duration,
Hold: *hold,
GroupSize: gs,
Scenario: *scenario,
}
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
done := make(chan struct{})
var runErr error
var report *load.Report
go func() {
defer close(done)
report, runErr = load.Run(cfg)
}()
select {
case <-done:
case <-stop:
fmt.Fprintln(os.Stderr, "interrupted")
os.Exit(130)
}
if runErr != nil {
fmt.Fprintln(os.Stderr, runErr)
os.Exit(1)
}
fmt.Printf("held %d connections for %s\n", b.Alive(), hold.String())
ch := make(chan os.Signal, 1)
signal.Notify(ch, os.Interrupt, syscall.SIGTERM)
select {
case <-time.After(*hold):
case <-ch:
}
fmt.Print(report.Format())
}