PHP项目场景压测如何串联多接口模拟流程

wen PHP项目 31

本文目录导读:

PHP项目场景压测如何串联多接口模拟流程

  1. 方案一:使用 JMeter 的“逻辑控制器”串联(推荐)
  2. 方案二:使用 Locust 编写 Python 脚本(灵活可控)
  3. 方案三:使用自研脚本 + 并发库(极致定制)
  4. 关键设计原则
  5. 实战建议
  6. 选型矩阵

在PHP项目中进行压测时,串联多接口模拟真实业务流(如用户登录->浏览商品->加入购物车->下单支付)比单接口压测更有价值,以下是几种主流的实现方案,按自动化程度和复杂度排序:

使用 JMeter 的“逻辑控制器”串联(推荐)

适用场景:无代码经验、需要可视化配置、快速出报告。

核心步骤

  1. 线程组:设置并发用户数、Ramp-Up时间、循环次数。
  2. HTTP Cookie管理器:自动保存登录后返回的 Cookie,用于后续接口。
  3. 接口请求:按顺序添加各接口的采样器。
  4. 正则表达式提取器 / JSON提取器:从上一个接口的响应中提取需要的数据(例如订单ID、token)。
  5. 断言:验证返回是否正确。

示例流程(登录 -> 下单)

Thread Group: 10用户, 循环5次
  ├─ HTTP Cookie 管理器
  ├─ HTTP 请求: POST /api/login (传入账号密码)
  │   └─ JSON提取器: 提取 $.data.token (保存为 ${token})
  ├─ 调试采样器(可选): 输出token验证
  ├─ HTTP 请求: POST /api/order (Header: Authorization: Bearer ${token})
  │   └─ 参数: product_id=1&quantity=2
  │   └─ JSON提取器: 提取 $.data.order_id (保存为 ${order_id})
  ├─ HTTP 请求: POST /api/pay (参数: order_id=${order_id})
  └─ 查看结果树 / 聚合报告

关键技巧

  • 参数化:用户数据从CSV文件读取,避免重复使用相同账号造成业务冲突。
  • 定时器:在接口之间添加“常数吞吐量定时器”模拟用户思考时间。

使用 Locust 编写 Python 脚本(灵活可控)

适用场景:需要动态逻辑、条件分支、复杂断言、长期维护的压测项目。

示例脚本

from locust import HttpUser, task, between
class BusinessFlowUser(HttpUser):
    wait_time = between(1, 3)  # 用户思考时间
    def on_start(self):
        """每个用户开始时的操作:登录并保存token"""
        with self.client.post("/api/login", json={
            "username": self.username,
            "password": "123456"
        }, catch_response=True) as resp:
            if resp.status_code == 200:
                self.token = resp.json()["data"]["token"]
                resp.success()
            else:
                resp.failure("Login failed")
        self.product_id = self.get_random_product()
    def get_random_product(self):
        # 从产品列表获取一个有效ID
        resp = self.client.get("/api/products?limit=100")
        return random.choice(resp.json()["data"])["id"]
    @task(3)  # 权重:该任务执行概率
    def browse_and_add_cart(self):
        headers = {"Authorization": f"Bearer {self.token}"}
        # 浏览商品
        self.client.get(f"/api/product/{self.product_id}", headers=headers)
        # 加入购物车
        self.client.post("/api/cart/add", json={
            "product_id": self.product_id,
            "quantity": random.randint(1,5)
        }, headers=headers)
    @task(1)
    def checkout_and_pay(self):
        # 创建订单
        resp = self.client.post("/api/order", json={
            "product_ids": [self.product_id]
        }, headers={"Authorization": f"Bearer {self.token}"})
        if resp.status_code == 200:
            order_id = resp.json()["data"]["order_id"]
            # 支付
            self.client.post("/api/pay", json={
                "order_id": order_id,
                "payment_method": "balance"
            }, headers={"Authorization": f"Bearer {self.token}"})

运行方式

locust -f flow_test.py --host=https://api.yourapp.com

使用自研脚本 + 并发库(极致定制)

适用场景:需要精确控制并发时序、与PHP项目代码交互(如直接调用框架函数)。

示例:PHP + Swoole 实现压测脚本

<?php
use Swoole\Coroutine\Http\Client;
// 参数配置
$concurrency = 20;
$users = loadUsersFromCSV('users.csv');
go(function () use ($concurrency, $users) {
    $wg = new \Swoole\Coroutine\WaitGroup();
    foreach ($users as $user) {
        $wg->add();
        go(function () use ($user, $wg) {
            $client = new Client('api.yourapp.com', 443, true);
            // 1. 登录
            $client->post('/api/login', ['username' => $user[0], 'password' => $user[1]]);
            if ($client->statusCode !== 200) return;
            $token = json_decode($client->body)->data->token;
            // 自动化添加鉴权头
            $client->setHeaders(['Authorization' => "Bearer $token"]);
            // 2. 获取随机商品
            $client->get('/api/product/random');
            $productId = json_decode($client->body)->id;
            // 3. 加入购物车
            $client->post('/api/cart/add', ['product_id' => $productId, 'quantity' => 2]);
            // 4. 模拟用户思考(0.5-2秒)
            \Swoole\Coroutine::sleep(mt_rand(5, 20) * 0.1);
            // 5. 下单支付
            $client->post('/api/checkout', ['address_id' => 1]);
            $orderId = json_decode($client->body)->order_id;
            $client->post('/api/pay', ['order_id' => $orderId, 'method' => 'wechat']);
            // 记录结果
            $client->close();
            $wg->done();
        });
    }
    $wg->wait();
});

关键设计原则

状态依赖性处理

  • 无状态接口(如商品列表):直接并发调用。
  • 有状态接口(需登录、需前置返回值):必须串联,但注意:
    • 失败重试:如果登录失败,不再继续后续接口。
    • 超时排队:使用队列管理“已登录”的token池。

避免业务冲突

  • 数据隔离:压测数据使用独立测试库,或用唯一标识(test_用户_时间戳)。
  • 幂等处理:接口支持幂等(订单号带UUID),避免重复下单。

数据参数化

用户信息 CSV 文件格式:
username,password,product_id
test1,123456,101
test2,123456,102

实战建议

  1. 先做单接口压测:定位瓶颈后再压测串联流程。
  2. 减少单次流程的数据依赖:将“获取商品列表”改为“使用预设商品ID”,避免接口返回为空时流程中断。
  3. 监控中间状态:在聚合报告中关注“登录成功率”、“下单成功率”、“支付成功率”,而不是只看整体TPS。
  4. 不要遗漏清理:压测结束后,需要清理测试产生的订单、优惠券等垃圾数据。

选型矩阵

方案 复杂流程 动态数据 并发控制 学习成本 报告可视化
JMeter 中等 需插件
Locust
自研脚本 最强 最强

推荐:如果团队没有交大的压测框架技术栈,从 JMeter + JSON提取器 开始最快,需要编写复杂业务逻辑(如随机跳转、条件分支)时,切换至 Locust。

抱歉,评论功能暂时关闭!