
在ThinkPHP6中结合Swoole实现高并发图片上传,可以通过以下步骤优化性能和并发处理能力:
1. 环境准备
安装Swoole扩展
pecl install swoole
# 或在Ubuntu/Debian中
sudo apt-get install php-swoole确保php.ini中启用扩展:
extension=swoole.so安装ThinkPHP6的Swoole适配包
composer require topthink/think-swoole2. 配置Swoole服务器
修改config/swoole.php,调整参数以支持高并发:
return [
'server' => [
'host' => '0.0.0.0',
'port' => 9501,
'options' => [
'worker_num' => swoole_cpu_num() * 2, // 工作进程数
'enable_coroutine' => true, // 开启协程
'max_request' => 1000, // 进程最大请求数
'upload_max_filesize' => 50 * 1024 * 1024, // 最大上传文件50MB
'package_max_length' => 100 * 1024 * 1024, // 请求包最大100MB
],
],
];3. 修改上传逻辑适配Swoole协程
控制器调整(app/controller/Upload.php)
public function upload()
{
$files = request()->file('image');
$results = [];
// 使用协程并行处理每个文件
$coroutines = [];
foreach ($files as $key => $file) {
$coroutines[] = Coroutine::create(function () use ($file, $key, &$results) {
try {
$validate = ['size' => 50*1024*1024, 'ext' => 'jpg,png,gif'];
$info = $file->validate($validate)->move('./uploads');
if ($info) {
$results[$key] = ['path' => $info->getSaveName()];
} else {
$results[$key] = ['error' => $file->getError()];
}
} catch (\Throwable $e) {
$results[$key] = ['error' => $e->getMessage()];
}
});
}
// 等待所有协程完成
Coroutine::join($coroutines);
return json(['data' => $results]);
}关键点:
- 协程并行处理:每个文件上传使用独立协程,避免阻塞。
- 共享数据安全:通过引用传递
$results,需注意协程间数据竞争,此处使用数组键确保顺序。
4. 使用Swoole异步文件写入
异步存储文件(替代move方法)
use Swoole\Coroutine\System;
// ...
$filePath = './uploads/' . uniqid() . '.' . $file->extension();
// 异步写入文件
$content = $file->getContent();
System::writeFile($filePath, $content);
$results[$key] = ['path' => $filePath];优势:
- 异步非阻塞IO提升并发吞吐量。
- 避免传统
move方法可能存在的阻塞问题。
5. 结合云存储进一步优化
配置阿里云OSS异步上传
use OSS\OssClient;
use Swoole\Coroutine;
// 在协程中异步上传到OSS
$ossClient = new OssClient(
config('oss.accessKeyId'),
config('oss.accessKeySecret'),
config('oss.endpoint')
);
Coroutine::create(function () use ($ossClient, $filePath, $object) {
$ossClient->uploadFile(config('oss.bucket'), $object, $filePath);
});6. 性能优化配置
调整Swoole参数(config/swoole.php)
'options' => [
'worker_num' => 8, // 根据CPU核心数调整
'task_worker_num' => 4, // 异步任务进程
'buffer_output_size' => 32 * 1024 * 1024, // 输出缓冲区
'max_coroutine' => 10000, // 最大协程数
],使用连接池管理资源
// 数据库/Redis连接池配置(避免协程间连接冲突)
\think\Db::setConfig([
'conn_pool' => true, // 启用连接池
'pool_size' => 50, // 连接池大小
]);7. 压力测试与监控
使用wrk进行并发测试
wrk -t4 -c100 -d30s http://localhost:9501/upload参数说明:
-t4:4个线程-c100:100个并发连接-d30s:持续30秒
监控Swoole服务状态
通过内置HTTP接口查看状态:
curl http://localhost:9501/stats输出示例:
{
"start_time": 1621567890,
"worker_num": 8,
"coroutine_num": 45,
"request_count": 12345
}8. 常见问题解决
问题1:上传大文件内存溢出
- 原因:默认Swoole将整个请求体加载到内存。
- 解决:启用临时文件存储:
'options' => [ 'http_parse_post' => true, 'upload_tmp_dir' => '/tmp/swoole_uploads', // 指定临时目录 ],
问题2:协程间数据污染
- 现象:
$results数组内容错乱。 - 解决:使用协程本地存储(Coroutine-Local Storage):
use Swoole\Coroutine; $results = new Coroutine\Channel(); Coroutine::create(function () use ($results) { // 处理文件... $results->push($result); }); $data = []; while ($result = $results->pop()) { $data[] = $result; }
总结
通过Swoole协程特性,ThinkPHP6的图片上传并发能力可提升10倍以上。核心步骤:
- 环境配置:安装Swoole扩展及适配包。
- 协程改造:使用
Coroutine::create并行处理每个文件。 - 异步IO优化:利用
System::writeFile或云存储SDK异步写入。 - 资源管理:配置连接池和合理Swoole参数。
- 监控调优:通过压力测试持续调整参数。
实际部署时需根据服务器硬件调整worker_num和max_coroutine,并确保文件存储服务(如OSS、NFS)具备高可用性。
评论
暂无评论
评论(0)