Skip to content

第 15 章 · 作为库使用

本章目标:不通过 locust 命令行,而是以 Python 库方式编程式启动压测,掌握 Environment/Runner 模型、嵌入 pytest 与 CI 流水线的方法。

15.1 Environment 与 Runner 模型

Locust 的命令行工具本质上是以下核心类的封装:

text
Environment(环境)
├── user_classes       → 注册的 User 类列表
├── events             → 事件系统
├── runner             → Runner 实例(控制启停)
│   └── greenlet       → 运行协程
└── web_ui             → Web UI 服务(可选)

编程式启动的最小代码:

python
from locust.env import Environment
from my_locustfile import MyTestUser

# 1. 创建 Environment,注册 User 类
env = Environment(user_classes=[MyTestUser])

# 2. 创建本地 Runner
env.create_local_runner()

# 3. 启动压测:500 个用户,每秒孵化 20 个
env.runner.start(5000, spawn_rate=20)

# 4. 阻塞等待压测完成
env.runner.greenlet.join()

15.2 控制压测生命周期

Runner 对象提供了完整的生命周期控制:

python
import time
from locust.env import Environment
from my_locustfile import MyTestUser

env = Environment(user_classes=[MyTestUser])
env.create_local_runner()

# 阶梯加压:逐步增加并发用户数
for users in [10, 50, 100, 200]:
    env.runner.start(users, spawn_rate=10)
    time.sleep(60)  # 每级持续 60 秒

# 手动停止
env.runner.quit()

带超时的自动停止

python
import gevent

def stop_after(seconds: int):
    gevent.sleep(seconds)
    print(f"{seconds}s 到期,自动停止")
    env.runner.quit()

# 5 分钟后自动结束
gevent.spawn(stop_after, 300)

env.runner.start(1000, spawn_rate=50)
env.runner.greenlet.join()
print("压测结束")

15.3 编程式访问统计数据

不用 Web UI,直接从代码中读取实时统计:

python
import time
from locust.env import Environment
from my_locustfile import MyTestUser

env = Environment(user_classes=[MyTestUser])
env.create_local_runner()
env.runner.start(100, spawn_rate=20)

# 每 10 秒打印一次统计摘要
for _ in range(6):
    time.sleep(10)
    stats = env.stats
    total = stats.total
    print(f"RPS: {total.current_rps:.1f} | "
          f"Avg: {total.avg_response_time:.0f}ms | "
          f"P95: {total.get_response_time_percentile(0.95):.0f}ms | "
          f"Failures: {total.num_failures}")

env.runner.quit()

常用统计属性:

属性说明
stats.total.current_rps当前每秒请求数
stats.total.avg_response_time平均响应时间(ms)
stats.total.get_response_time_percentile(0.95)P95 响应时间
stats.total.num_requests总请求数
stats.total.num_failures总失败数
stats.errors错误详情字典

15.4 嵌入 pytest:性能回归测试

将轻量级性能检查嵌入单元测试流程——每次 CI 构建自动验证关键接口的响应时间:

python
# test_perf.py
import pytest
from locust.env import Environment
from locust_stats import check_thresholds  # 自定义断言辅助
from my_locustfile import ApiUser


@pytest.fixture(scope="module")
def perf_env():
    """创建并清理 Locust 环境"""
    env = Environment(user_classes=[ApiUser])
    env.create_local_runner()
    yield env
    env.runner.quit()


class TestAPIPerformance:

    def test_home_page_under_200ms(self, perf_env):
        """首页平均响应 < 200ms"""
        perf_env.runner.start(20, spawn_rate=20)
        time.sleep(30)  # 运行 30 秒收集数据

        avg = perf_env.stats.total.avg_response_time
        assert avg < 200, f"首页平均响应 {avg:.0f}ms 超过阈值 200ms"

    def test_error_rate_below_1pct(self, perf_env):
        """错误率 < 1%"""
        total = perf_env.stats.total
        if total.num_requests > 0:
            rate = total.num_failures / total.num_requests
            assert rate < 0.01, f"错误率 {rate:.2%} 超过阈值 1%"

注意事项

CI 中跑性能测试要固定资源规格(同一台 runner、同样的网络条件),否则结果不可比。建议在独立的专用节点上运行。

15.5 启用 Web UI 的编程模式

编程式运行时也可以开启 Web UI 来监控进度:

python
env = Environment(user_classes=[MyTestUser])
env.create_local_runner()

# 同时启动 Web UI
env.create_web_ui()

env.runner.start(500, spawn_rate=25)
env.web_ui.greenlet.join()  # 阻塞直到手动停止或进程退出

访问 http://localhost:8089 可实时查看图表和统计数据。

Worker 不适合编程式创建

官方文档明确指出:虽然技术上可以通过 create_worker_runner() 创建 worker,但这几乎从不合理——每个 worker 必须是独立 Python 进程。分布式 worker 请使用标准 CLI 命令 locust --worker ...

15.6 跳过 Monkey-Patching

在某些场景下(如在 Jupyter Notebook 中调试),monkey-patching 可能引发冲突。可以在导入 locust 前设置环境变量跳过:

python
import os
os.environ["LOCUST_SKIP_MONKEY_PATCH"] = "1"

# 然后再导入 locust
from locust import User, task

性能影响

跳过 monkey-patching 后,所有 I/O 操作变为阻塞式,单进程只能串行执行任务。仅用于调试场景。

本章小结

  • Environmentcreate_local_runner()runner.start(users, spawn_rate) 三步启动压测;
  • env.stats 提供编程式访问 RPS、响应时间分位数、错误率等数据;
  • 将轻量性能检查嵌入 pytest fixture,实现 CI 自动化性能回归;
  • Web UI 可通过 create_web_ui() 在编程模式下启用;
  • 分布式 worker 请始终使用 CLI 启动。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. 编程式启动 Locust 压测的第一个步骤是什么?

2. 如何获取当前的 P95 响应时间?

3. 为什么不应该用 create_worker_runner() 创建 worker?

4. 在什么情况下应该设置 LOCUST_SKIP_MONKEY_PATCH 环境变量?

🛠️ 动手实践

  1. 用编程方式编写一个阶梯加压脚本:从 10 用户开始,每分钟翻倍,直到达到 500 用户。
  2. 将一个 API 的 P99 响应时间检查嵌入 pytest 测试,并在本地运行验证。
  3. 尝试在编程模式中同时启用 Web UI 和自定义统计回调,观察两者是否正常工作。

下一章学习 插件与扩展 生态,定制属于你的 Locust。