本文目录导读:

我来系统地分析ThinkPHP项目慢请求的问题和优化方案。
问题诊断方法
开启调试模式分析
// .env 或 config/app.php
'debug' => true,
'trace' => [
'type' => 'html', // 或 'console'
],
使用性能分析工具
// 在控制器中添加性能分析
public function index()
{
// 开始计时
$startTime = microtime(true);
$startMemory = memory_get_usage();
// 业务代码...
// 结束分析
$endTime = microtime(true);
$endMemory = memory_get_usage();
trace('执行时间:' . ($endTime - $startTime) . '秒');
trace('内存使用:' . ($endMemory - $startMemory) . '字节');
return view();
}
日志分析
// config/log.php
return [
'type' => 'File',
'path' => '../runtime/log/',
'level' => ['error', 'warning', 'sql', 'info'],
'json' => false,
];
常见性能瓶颈及优化
数据库查询优化
问题示例
// 低效查询
$users = Db::name('users')->select(); // 全表查询
foreach($users as $user) {
$orders = Db::name('orders')->where('user_id', $user['id'])->select(); // N+1问题
}
// 优化方案
$users = Db::name('users')->select();
$userIds = array_column($users, 'id');
$orders = Db::name('orders')->whereIn('user_id', $userIds)->select();
$orderMap = [];
foreach($orders as $order) {
$orderMap[$order['user_id']][] = $order;
}
优化建议
// 1. 使用查询构造器优化
Db::name('users')
->field('id, name, email') // 只查需要的字段
->where('status', 1)
->limit(20)
->select();
// 2. 使用模型关联预加载
User::with(['orders' => function($query) {
$query->where('status', 1);
}])->select();
// 3. 使用原生SQL复杂查询
$result = Db::query("SELECT id, COUNT(*) as count FROM orders GROUP BY user_id HAVING COUNT(*) > 10");
缓存优化
配置Redis缓存
// config/cache.php
return [
'type' => 'Redis',
'host' => '127.0.0.1',
'port' => 6379,
'password' => '',
'select' => 0,
'timeout' => 0,
'expire' => 3600,
'persistent' => false,
'prefix' => 'think_',
];
// 使用缓存
use think\facade\Cache;
// 缓存首页数据
if (!Cache::has('home_data')) {
$data = Db::name('articles')->select();
Cache::set('home_data', $data, 3600);
}
$data = Cache::get('home_data');
缓存策略示例
class ArticleService
{
public function getArticleList($page = 1)
{
$cacheKey = "article_list_{$page}";
// 先从缓存读取
$list = Cache::get($cacheKey);
if (empty($list)) {
// 缓存不存在,查询数据库
$list = Article::with(['author', 'tags'])
->where('status', 1)
->order('create_time', 'desc')
->paginate(10);
// 写入缓存
Cache::set($cacheKey, $list, 600);
}
return $list;
}
}
代码优化
优化循环处理
// 不推荐
$result = [];
foreach($list as $item) {
$item['time'] = date('Y-m-d', strtotime($item['create_time']));
$result[] = $item;
}
// 推荐:使用批量处理
$ids = array_column($list, 'id');
$allData = Db::name('data')->whereIn('id', $ids)->select();
$dataMap = array_column($allData, null, 'id');
减少冗余操作
// 避免重复查询
$product = Db::name('product')->find(1); // 第一次查询
// ... 业务逻辑
$product = Db::name('product')->find(1); // 第二次查询,应该用变量
// 正确做法
$product = Db::name('product')->find(1);
$productData = $product; // 使用变量复用
页面静态化
public function index()
{
$html = Cache::get('page_home');
if (empty($html)) {
ob_start();
// ... 渲染视图
echo view('index/index')->getContent();
$html = ob_get_clean();
Cache::set('page_home', $html, 600);
}
return $html;
}
数据库配置优化
// config/database.php
return [
'type' => 'mysql',
'host' => '127.0.0.1',
'database' => 'thinkphp',
'username' => 'root',
'password' => '',
// 连接池配置
'connectionPool' => [
'enabled' => true,
'max_connections' => 100,
'min_connections' => 10,
'wait_timeout' => 3,
],
// 读写分离
'read' => [
'host' => ['127.0.0.1'],
],
'write' => [
'host' => ['127.0.0.1'],
],
];
框架配置优化
优化自动加载
// composer.json 优化
"autoload": {
"psr-4": {
"app\\": "app"
},
"classmap": [
"app/common"
]
}
// 执行命令
composer dump-autoload -o
关闭不必要功能
// config/app.php
'environment' => 'product', // 生产环境
'debug' => false, // 关闭调试模式
'default_timezone' => 'Asia/Shanghai',
'error_reporting' => E_ALL & ~E_DEPRECATED & ~E_NOTICE,
// 关闭路由缓存(生产环境开启)
'route' => [
'check_cache' => true,
],
服务器层面优化
PHP配置优化
; php.ini memory_limit = 256M max_execution_time = 30 opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 4000 realpath_cache_size = 4096K realpath_cache_ttl = 600
Nginx配置优化
# nginx配置
worker_processes auto;
worker_connections 1024;
fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=phpcache:100m inactive=60m;
server {
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 启用缓存
fastcgi_cache phpcache;
fastcgi_cache_valid 200 60m;
fastcgi_cache_key $host$request_uri;
}
}
MySQL优化
-- 优化查询 CREATE INDEX idx_user_id ON orders(user_id); CREATE INDEX idx_create_time ON articles(create_time); -- 分析查询 EXPLAIN SELECT * FROM orders WHERE user_id = 100; -- 开启慢查询日志 SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 2;
性能监控方案
自定义性能监控中间件
// app/middleware/PerformanceMonitor.php
class PerformanceMonitor
{
public function handle($request, \Closure $next)
{
$start = microtime(true);
$response = $next($request);
$end = microtime(true);
$cost = ($end - $start) * 1000; // ms
// 记录慢请求
if ($cost > 1000) {
\think\facade\Log::warning('慢请求', [
'url' => $request->url(),
'cost' => $cost . 'ms',
'ip' => $request->ip(),
'time' => date('Y-m-d H:i:s')
]);
}
$response->header('X-Trace-Time', $cost);
return $response;
}
}
SQL性能监控
// 在数据库配置中启用
'query_log' => true,
// 或自定义监听
Db::listen(function ($sql, $time, $explain) {
if ($time > 0.1) {
Log::write("SQL耗时" . $time . "s: " . $sql, 'sql');
}
});
常见问题快速解决方案
N+1查询问题
// 问题代码
$articles = Article::select();
foreach ($articles as $article) {
$article->author; // 每次触发查询
}
// 优化代码
$articles = Article::with('author')->select();
foreach ($articles as $article) {
$article->author; // 已预加载
}
大数据量处理
// 使用分块处理
Db::name('large_table')->chunk(100, function($records) {
foreach ($records as $record) {
// 处理记录
}
});
图片/文件加载优化
// 使用懒加载
// 模板中
<img src="__STATIC__/img/loading.gif" data-src="__IMG__/{$img.src}" class="lazyload">
// 配合JS库实现懒加载
建议持续监控请求响应时间,建立性能基线,定期分析和优化,使用性能监控工具(如Xdebug、Blackfire.io)进行深度分析,找出瓶颈所在。