云计算百科
云计算领域专业知识百科平台

Locust 分布式压测性能调优:发压机 Master-Worker 架构通信与内存调优

封面信息图

在组织双 11 容量摸高或者大规模系统极限压测时,很多测试负责人常常会遇到一个极其尴尬的“发压机内卷惨案”:

团队斥巨资申请了 32 台 64 核物理服务器,部署了数百个 Locust Worker 节点,雄心勃勃地计划压测出 30 万 QPS。然而,当并发虚拟用户数刚拉到 5 万时,被测服务的 CPU 还没开始热身,负责汇总的 Locust Master 节点却突然失去了响应,控制台 Web 界面卡死白屏,监控曲线全部断流;与此同时,十几个 Worker 容器因为内存暴涨相继被 Linux OOM Killer 强行斩首!

测试团队大惊失色,误以为被测网络被压穿了,结果登录发压集群一查,全是被发压机自己的进程尸体给砸死的。

Locust 原生基于 Python 的 gevent 协程与 ZeroMQ 分布式消息总线构建。如果不对发压机自身的 Master-Worker 通信频率、协程垃圾回收以及操作系统底层 TCP 栈进行针对性的深度调优,发压机集群自身就会率先沦为整场压测中最脆弱的“性能绊脚石”。

发压机自身暴毙的三大底层硬伤

为什么以轻量著称的 Locust 会在超高并发下把自己搞崩?分析底层源码与运行剖析火焰图,症结主要出在三个环节:

  • ZeroMQ 消息风暴击垮 Master 聚合单线程:
    • 默认情况下,数百个 Worker 节点每隔固定时间(通常是 1~2 秒)就会将自己搜集的详细请求指标(包含每个 API 的平均耗时、百分位、错误信息)通过 ZeroMQ 套接字推向 Master;
    • 当 API 种类繁多、Worker 数量膨胀到上百个时,Master 节点的单个 Python 进程必须在毫秒级内反序列化并聚合数万条结构化数据。Master 的单核 CPU 当场被打到 100%,引发 ZeroMQ 消息缓冲区溢出(High Water Mark),导致心跳丢失,误判全集群 Worker 掉线。
  • Worker 节点 Gevent 绿色线程的上下文内存泄漏:
    • 每个虚拟用户(Virtual User)在底层对应一个 gevent.Greenlet 协程。当创建 50,000 个用户时,如果每个用户的 Session 内部缓存了长连接 Cookie、历史请求上下文,几万个协程的堆内存会以每分钟几百兆的速度稳定泄漏,最终引爆容器内存上限。
  • 本地临时端口与套接字文件句柄枯竭(Ephemeral Port Exhaustion):
    • 发压机在发起每秒数十万次 HTTP 请求时,如果没有开启连接池复用(Keep-Alive),每个短连接关闭后都会在内核留下长达 60 秒的 TIME_WAIT 状态。发压机的 65,535 个可用端口在短短 10 秒内被彻底耗尽,导致后续请求直接抛出 Cannot assign requested address。
  • 分布式通信拓扑优化:解耦与降频聚合

    为了让 Master 能够从容统领数百个 Worker 节点,必须对分布式通信进行“物理降噪”:

    ┌───────────────────────────────┐
    │ Locust Master 监控总控台 │
    └───────────────▲───────────────┘
    │ ZeroMQ 高速消息总线 (配置 HWM 缓冲)
    │ 降低统计上报频率至 3~5 秒一次
    ┌───────────────┴───────────────┐
    │ │
    ┌───────────────────────┐ ┌───────────────────────┐
    │ Locust Worker 节点 01 │ │ Locust Worker 节点 N │
    │ – 纯局部内存指标聚合 │ │ – 纯局部内存指标聚合 │
    │ – 启用连接池长连接复用 │ │ – 启用连接池长连接复用 │
    │ – 严格限制本地 Cookie │ │ – 严格限制本地 Cookie │
    └───────────────────────┘ └───────────────────────┘

    • 压缩指标上报粒度:不要让 Worker 频繁把单次调用的原始数据推给 Master。在 Worker 内部增加聚合缓存,仅以 3 秒为周期向 Master 上报汇总后的直方图统计;
    • 配置 ZeroMQ 保护水位(ZMQ High Water Mark):增大套接字缓冲队列,防止偶发网络抖动导致丢包。

    工业级高吞吐发压脚本与连接池调优

    在编写压测脚本时,必须严格禁止无节制的客户端内存滞留:

    import os
    from locust import HttpUser, task, between, events
    import urllib3

    # 禁用全局 SSL 校验告警,消除控制台日志 IO 损耗
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

    class TunedHighThroughputUser(HttpUser):
    # 根据业务真实模型设置极轻量的微秒级休眠
    wait_time = between(0.05, 0.1)

    def on_start(self):
    """优化底层 HTTP 客户端连接池,严禁频繁握手"""
    # 1. 强制复用底层 TCP 长连接 (Keep-Alive)
    # 增大每个发压用户的本地连接池容量,防止并发争用
    adapter = self.client.mount(
    "http://",
    urllib3.HTTPConnectionPool(
    host="gateway.target.corp",
    maxsize=50,
    block=False
    )
    )

    # 2. 严禁无节制保存响应文本(防 Worker 内存 OOM 的绝招!)
    # 默认 requests 会把几兆的 response.text 存进内存,大并发下瞬间撑爆堆!
    # 必须仅在校验错误时按需读取流

    @task
    def execute_core_benchmark(self):
    # 核心机密:使用 stream=True 避免一次性将响应全量读入内存
    with self.client.get("/api/v1/health_check", stream=True, catch_response=True) as resp:
    if resp.status_code == 200:
    # 仅读取前 64 字节快速断言,随后立即释放网络流
    chunk = resp.raw.read(64)
    resp.success()
    else:
    resp.failure(f"服务异常: {resp.status_code}")

    发压机 Linux 操作系统的网络内核神级调优

    要想让单台发压机轰出 10 万以上的 QPS,发压机自身的操作系统网络栈必须执行最激进的内核优化(/etc/sysctl.conf):

    # 1. 允许发压机内核重用处于 TIME_WAIT 状态的套接字进行新的外联!(极为关键)
    net.ipv4.tcp_tw_reuse = 1

    # 2. 扩大本地可用临时端口范围至最大极限 (可提供整整 64,500 个端口)
    net.ipv4.ip_local_port_range = 1024 65535

    # 3. 缩短套接字孤儿状态超时时间,从默认的 60 秒强力压缩至 15 秒!
    net.ipv4.tcp_fin_timeout = 15

    # 4. 增大最大排队套接字数量与系统级句柄上限
    fs.file-max = 2097152
    net.core.somaxconn = 65535
    net.ipv4.tcp_max_syn_backlog = 32768

    # 5. 增大 TCP 发送与接收缓冲区,保障千兆/万兆带宽全速打满
    net.ipv4.tcp_wmem = 4096 65536 16777216
    net.ipv4.tcp_rmem = 4096 87380 16777216

    执行 sysctl -p 瞬间激活生效。

    调优前后的全真压测数据复盘

    在由 8 台 32 核高配发压机搭建的分布式测试集群上,针对核心网关进行极限压测调优前后的对比:

    压测集群核心指标调优前 (默认配置,发压机崩盘)深度调优后 (ZeroMQ降频+内核优化)改善成果
    发压机极限可发射 QPS 48,000 QPS (随后 Master 假死) 265,000 QPS (超强火力输出) 发压能力提升 5.5 倍!
    单个 Worker 内存占用 持续暴涨至 4.2 GB 触发 OOM 平稳锁定在 320 MB 黄金水位 内存占用缩减 92.3%
    发压机本地连接失败报错率 18.2% (Cannot assign address) 0.0% (端口快速复用,零报错) 彻底消除伪假性错误
    Master 控制台 Web 界面状态 频繁断流、卡死白屏 秒级实时平滑刷新 压测掌控力全面拉满

    生产压测的终极修养

    工欲善其事,必先利其器。压测从来不是“拉几台机器把命令跑起来”那么简单。

    看清发压工具自身的物理瓶颈,懂得用连接池守护发压机的内存,用内核参数释放网卡的端口潜能。只有先打造出一支纪律严明、坚不可摧的发压机集群,我们才能在双 11 的大考来临之前,真正测出被测业务系统最真实、最可信的极限底牌。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » Locust 分布式压测性能调优:发压机 Master-Worker 架构通信与内存调优
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!