大数跨境

PHP容量评估实战:利用getrusage计算真实CPU耗时

PHP容量评估实战:利用getrusage计算真实CPU耗时 wordpress知识
2026-10-23
4

告别响应时间误区:基于 getrusage 的 PHP 容量精准评估

许多开发者在评估 CPU 负载时,习惯直接使用接口响应时间进行计算。然而,监控中看到的接口响应时间大部分消耗在等待 MySQL、Redis、网络 IO 及锁资源上,此期间 CPU 处于空闲状态。直接依据总响应时间预估 CPU 配置,往往导致服务器资源浪费或压测结果与线上表现严重不符,引发突发卡顿。

本文将介绍如何利用 PHP 的 getrusage 函数获取单次请求的真实 CPU 耗时(tc),并结合 Little 定律,构建一套可落地、可量化的 PHP 服务容量评估方案,从而精准估算 CPU 核心数与内存需求。

关键指标辨析:tw 与 tc

tw(Wall Time,墙上时间):指从请求抵达 Nginx 到数据返回前端的总耗时,即通常通过 microtime(true) 统计的响应时间。它包含业务计算、数据库等待、Redis 等待、网络及锁等待时间,直接决定用户感知的快慢。

tc(CPU Time,CPU 耗时):指请求执行期间,CPU 真正用于执行代码的时间。等待 IO、sleep 或等待数据库返回的时间不计入内。该指标才是评估 CPU 核心需求的真实依据。

例如,某接口 tw 为 200ms,但其中真正的 CPU 耗时 tc 可能仅为 20ms,剩余 180ms 均为 IO 等待。因此,单纯依赖响应时间估算 CPU 必然导致高估。

利用 getrusage 获取真实 tc

getrusage() 是 PHP 对 Linux 系统调用 getrusage(2) 的封装,用于读取进程资源消耗统计。该函数在 Windows 下支持不完善,仅推荐在 Linux 环境下配合 PHP-FPM 使用。

getrusage(int $mode = 0): array|false
  • RUSAGE_SELF (0):统计当前进程,Web 接口评估默认使用此模式。
  • RUSAGE_CHILDREN (1):统计已结束并被父进程回收的子进程资源,一般不用于 Web 接口评估。

核心返回字段解析

重点关注以下两组 timeval 格式(秒 + 微秒)的时间数据:

  • ru_utime:用户态 CPU 时间,主要用于 PHP 业务逻辑运算。
  • ru_stime:内核态 CPU 时间,涵盖文件读写、Socket 通信及系统调用等内核操作。

单次请求 CPU 耗时计算公式:

tc = 结束采样 (utime + stime) − 开始采样 (utime + stime)

由于 PHP-FPM 进程复用机制,必须在请求的开始和结尾分别采样并计算差值,才能获得当前请求的准确 CPU 耗时。

埋点代码实现

可将以下逻辑放入项目全局中间件或基础控制器中:

$start = getrusage();
// ========== 这里是你的业务代码 ==========
// $data = Db::name('order')->where(...)->select();
// ========================================
$end = getrusage();

// 计算用户态CPU增量(微秒)
$utime = ($end['ru_utime.tv_sec'] - $start['ru_utime.tv_sec']) * 1e6
    + ($end['ru_utime.tv_usec'] - $start['ru_utime.tv_usec']);

// 计算内核态CPU增量(微秒)
$stime = ($end['ru_stime.tv_sec'] - $start['ru_stime.tv_sec']) * 1e6
    + ($end['ru_stime.tv_usec'] - $start['ru_stime.tv_usec']);

$tc = ($utime + $stime) / 1000000; // 单位:秒,CPU耗时
$tw = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']; // 单位:秒,墙上总耗时

// 写入日志:url、状态码、tc、tw
// Log::info("request stat", compact('tc','tw'));

日志输出示例:

url:/api/order/list  tc:0.019  tw:0.162

通过长期收集日志,可统计各接口的平均 tc,作为容量评估的基准数据。

getrusage 的使用边界

  • 仅统计当前 PHP-FPM 进程。pcntl_fork 子进程、Think-Queue、Workerman、Swoole 协程的 CPU 消耗不会被统计;队列任务需在脚本内部单独埋点。
  • 无法统计 MySQL、Redis、Nginx 等独立进程的资源开销。若同机部署数据库,需单独预留 CPU 余量。
  • sleep()、usleep() 不会增加 tc,符合 IO 密集型业务特征。
  • 适用于同步 PHP-FPM 接口,不适用于多线程场景。

基于 Little 定律的容量评估模型

获取 tw 和 tc后,引入排队论中的 Little 定律串联流量指标:

C = QPS * tw

  • C:平均并发请求数,即同一时刻在 PHP-FPM 中处理的请求总数(含等待 IO 的请求)。
  • QPS:每秒完成的请求数量。
  • tw:接口墙上响应时间(单位:秒)。

并发越高并不意味着 CPU 压力越大。PHP 业务多为 IO 密集型,大量并发请求往往阻塞在等待数据库或缓存返回,期间不消耗 CPU。因此,Little 定律计算的并发 C 主要用于评估内存需求,指导设置 php-fpm 的 pm.max_children,而不能直接用于评估 CPU。

CPU 核心数评估公式:

CPU核数 = (QPS * tc) / 0.7

其中 0.7 为安全水位系数,用于避免高峰期 CPU 满载,预留缓冲空间。

实战案例

假设某接口平均墙上时间 tw=0.2s,峰值 QPS=50:

  1. 计算并发:C = 50 * 0.2 = 10。峰值平均并发约 10,配置 max_children 时应大于此数值并预留余量。
  2. 计算 CPU:经日志统计,该接口平均 tc=0.02s。
    CPU核数 = (50 * 0.02) / 0.7 ≈ 1.43。
  3. 最终选型:向上取整。若 MySQL 与 Web 同机部署,需叠加数据库开销,建议选择 2 核或 4 核服务器。

总结:PHP 服务器规格评估步骤

  1. 在全局中间件埋入 getrusage,采集各接口的 tc、tw 并写入日志。
  2. 统计业务峰值 QPS,以及各接口的平均 tc、tw。
  3. 利用 Little 定律 C=QPS*tw 计算平均并发,据此估算内存并设置 php-fpm max_children。
  4. 利用公式 CPU核数 = (QPS * tc)/0.7 估算 CPU 规格;若同机部署 MySQL,需额外增加余量。
  5. 上线后持续监控 htop、free、慢 SQL 及日志,根据真实数据进行迭代调整。
【声明】内容源于网络
0
0
wordpress知识
各类跨境出海行业相关资讯
内容 382
粉丝 0
wordpress知识 各类跨境出海行业相关资讯
总阅读14.1k
粉丝0
内容382