通过ThinkPHP的中间件机制,可以便捷地记录每个请求的执行时间和内存消耗,适用于快速定位慢请求。
app/middleware目录下新建PerformanceMiddleware.php,代码如下:namespace app\middleware;
use think\facade\Log;
use think\middleware\BaseMiddleware;
class PerformanceMiddleware extends BaseMiddleware
{
public function handle($request, \Closure $next)
{
$start_time = microtime(true); // 记录开始时间
$response = $next($request); // 执行请求
$end_time = microtime(true); // 记录结束时间
$cost_time = $end_time - $start_time; // 计算耗时
$memory_usage = memory_get_peak_usage(true) / 1024 / 1024; // 峰值内存(MB)
Log::info("请求路径:{$request->path()} | 耗时:{$cost_time}秒 | 内存:{$memory_usage}MB"); // 写入日志
return $response;
}
}
app/middleware.php中全局注册该中间件(或指定路由分组注册):return [
\app\middleware\PerformanceMiddleware::class,
];
runtime/log目录下,包含请求路径、耗时和内存使用情况,便于后续分析。借助成熟的监控平台,实现全面的性能追踪、报警和可视化,适合生产环境。
prometheus.yml,添加ThinkPHP应用的抓取目标(如job: 'thinkphp');think-prometheus)将性能指标(请求量、耗时、错误率)暴露为Prometheus格式的HTTP端点;ThinkPHP Dashboard),实现实时可视化。newrelic-php5扩展);ThinkPHP的日志系统可记录错误、慢查询和自定义信息,是基础的性能监控手段。
config/log.php中设置日志级别(建议生产环境开启error和warn)和存储路径:return [
'default' => 'file',
'channels' => [
'file' => [
'type' => 'file',
'path' => runtime_path('log'), // 日志存储路径
'level' => ['error', 'warn', 'info'], // 日志级别
],
],
];
\think\facade\Log::info("数据库查询耗时:{$query_time}秒", ['sql' => $sql]);
\think\facade\Log::warn("接口响应超时:{$cost_time}秒", ['path' => $request->path()]);
tail、grep等命令或ELK等工具分析历史性能问题。通过Linux自带的命令行工具,监控服务器资源使用情况,快速定位系统瓶颈。
top/htop:实时查看CPU、内存占用率,排序进程资源消耗;vmstat 1:每秒输出系统整体状态(进程、内存、IO、CPU),关注r(运行队列)、b(阻塞进程)、free(空闲内存);iostat -x 1:监控磁盘IO负载(%util表示磁盘利用率,await表示平均IO等待时间);netstat -tulnp:查看网络连接状态(端口占用、连接数),识别网络瓶颈。top命令发现PHP-FPM进程占用过高,可通过调整pm.max_children参数优化;通过iostat发现磁盘IO过高,可优化数据库索引或增加缓存。缓存是提升ThinkPHP性能的关键手段,能有效减少重复计算和数据库查询。
cache方法缓存整个页面(适用于静态内容):public function index()
{
return cache('home_page', function() {
// 页面生成逻辑
return view('index');
}, 3600); // 缓存1小时
}
config/template.php中开启模板缓存:return [
'tpl_cache' => true, // 开启模板缓存
'tpl_cache_time' => 3600, // 缓存时间(秒)
];
$data = Cache::store('redis')->remember('category_list', 3600, function() {
return Db::name('category')->select();
});
以上方法覆盖了从基础日志到专业工具的全链路性能监控方案,可根据项目规模和需求选择合适的组合。