Skip to content

第 2 章 · 安装与第一个脚本

本章目标:理解 locustfile.py 的基本结构,掌握 HttpUser 类、@task 装饰器和 between() 等待时间三个核心概念,写出并运行你的第一个完整压测。

2.1 locustfile 的最小结构

一个合法的 locustfile 只需满足一条规则:至少包含一个继承自 User(或其子类 HttpUser)的类

python
# locustfile.py
from locust import HttpUser, task, between


class QuickstartUser(HttpUser):
    wait_time = between(1, 5)

    @task
    def hello_world(self):
        self.client.get("/hello")
        self.client.get("/world")

    @task(3)
    def view_items(self):
        for item_id in range(10):
            self.client.get(f"/item?id={item_id}", name="/item")

    def on_start(self):
        self.client.post("/login", json={"username": "foo", "password": "bar"})

这段代码包含了 Locust 的四大核心概念,接下来逐一拆解。

2.2 HttpUser:模拟一个用户

HttpUser 是 Locust 内置的用户类,专门用于 HTTP 压测。当测试启动时:

  1. Locust 为每个虚拟用户创建一个该类的实例
  2. 每个实例获得一个 client 属性——它是 HttpSession 的实例,负责发起 HTTP 请求;
  3. 每个用户运行在自己的 greenlet 协程中,互不阻塞。
python
class MyUser(HttpUser):
    host = "https://httpbin.org"  # 也可以在类里声明默认主机

    @task
    def get_ip(self):
        resp = self.client.get("/ip")  # 等价于 requests.get("https://httpbin.org/ip")
        print(resp.json())

client 与 requests 的关系

self.client.get() / .post() 的参数签名与 requests 库几乎完全一致(支持 headersjsonparams 等)。如果你已经学过本站 HTTP 请求课程,可以无缝迁移。

2.3 @task:声明要执行的任务

@task 装饰的方法就是虚拟用户的"行为"。每个用户会循环执行这些方法,每次随机挑一个:

python
@task
def browse_homepage(self):
    self.client.get("/")


@task(3)  # 权重为 3
def browse_product(self):
    self.client.get("/product/1")

@task(3) 表示这个任务被选中的概率是权重 1 任务的 3 倍——模拟"用户浏览商品比看首页更频繁"的真实场景。

2.4 between():控制思考时间

真实用户不会像机器人一样不停发请求。wait_time 属性定义了两次任务之间的等待:

python
from locust import between

wait_time = between(1, 5)  # 每次任务后随机等 1~5 秒

没有等待时间的话,所有用户会以最快速度轰炸目标系统——那是压力测试而不是负载测试。第 4 章会详细讲解更多等待策略。

2.5 运行与查看结果

把脚本保存为 locustfile.py,在终端运行:

bash
$ locust
[INFO] Starting web interface at http://0.0.0.0:8089

打开浏览器访问 http://localhost:8089

  1. Number of users:总并发用户数(如 50)
  2. Ramp up:每秒新增用户数(如 5/s)
  3. Host:目标地址(如 https://httpbin.org

点击 Start 后切换到 Charts 标签页,你会看到三条实时曲线:

  • RPS:每秒请求数
  • Response Times:响应时间(中位数和百分位)
  • Number of Users:当前运行的虚拟用户数

如何判断到达瓶颈

如果 RPS 不再增长但响应时间急剧上升,说明目标系统已饱和。如果响应时间保持平稳且 RPS 未达标,说明还需要加压。

本章小结

  • locustfile 就是普通 Python 模块,只需含至少一个 User 子类;
  • HttpUser.client 发请求,用法与 requests 一致;
  • @task 装饰器声明任务,@task(N) 控制选中概率;
  • wait_time = between(1, 5) 模拟真实用户的思考停顿;
  • Web UI 默认端口 8089,Charts 页面实时展示 RPS / 响应时间 / 用户数。

🧪 随堂测验

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

1. 一个合法的 locustfile 至少需要包含什么?

2. @task(3) 中数字 3 的含义是什么?

3. wait_time = between(1, 5) 表示什么?

4. HttpUser 实例的 self.client 属性是什么类型?

🛠️ 动手实践

  1. 编写一个包含两个任务的 locustfile:一个 GET /get(权重 1)、一个 POST /post(权重 2),目标是 https://httpbin.org
  2. 在 Web UI 中分别用 10 用户/2 spawn-rate 跑一次,截图记录 RPS 和响应时间曲线。
  3. 删掉 wait_time = between(1, 5) 这行再跑一次,对比 RPS 变化并解释原因。

完成后进入第 3 章