PHP后端Swoole应用及协程、API调用等技术疑问咨询
PHP+Nginx转Swoole的性能优化与问题解答
我用PHP/Nginx做App后端,担心高并发下PHP同步特性导致性能瓶颈,用MacOS终端的wrk工具做了压测:
wrk -t4 -c100 http://103.22.110.32:80/a.php
测试结果:
Running 10s test @ http://103.22.110.32:80/a.php 4 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 111.87ms 30.31ms 430.54ms 93.69% Req/Sec 207.00 46.30 313.00 79.08% 8159 requests in 10.05s, 1.58MB read Non-2xx or 3xx responses: 8159 Requests/sec: 812.05 Transfer/sec: 160.98KB
从结果看,当前最大并发约800次/秒,要是有8万用户请求,得等大概100秒。了解到Swoole支持异步/协程,能把性能提至6万次/秒以上,于是写了Swoole版本的代码。
原PHP后端代码
$tasknum = $request->get['Task']; switch ($tasknum) { case "task": Code for task A break; case "taskb": Code for task B break; case "taskc": Code for task c break; }
我编写的Swoole代码
use Swoole\Http\Server; use Swoole\Coroutine; require_once 'vendor/autoload.php'; $server = new Server("0.0.0.0", 81); $server->on('Request', function ($request, $response) { // Handle incoming requests $tasknum = $request->get['Task']; switch ($tasknum) { case "task": $response->header("Content-Type", "text/plain"); $response->end("Task A executed successfully."); break; case "taskb": $response->header("Content-Type", "text/plain"); $response->end("Task A executed successfully."); break; case "taskc": $response->header("Content-Type", "text/plain"); $response->end("Task A executed successfully."); break; case "a": $response->header("Content-Type", "text/plain"); $response->end("ppppirnt aaaa"); break; } }); $server->start();
问题解答
1. 当前使用Swoole的方式是否正确?能否使用Coroutine(协程)优化?
当前的Swoole Http Server用法是正确的,能正常处理HTTP请求,但你现在的代码只是同步返回响应,没用到协程的核心优势。如果你的Task A/B/C包含IO操作(比如数据库查询、HTTP请求、文件读写),完全可以用协程优化:
Swoole 4+版本中,onRequest回调默认运行在协程环境下,你只需要把同步IO操作替换成Swoole提供的协程客户端(比如Swoole\Coroutine\MySQL、Swoole\Coroutine\Http\Client)即可。举个优化示例:
case "taskc": // 用协程MySQL处理IO密集型任务 go(function() use ($response) { $mysql = new Swoole\Coroutine\MySQL(); $mysql->connect([ 'host' => '127.0.0.1', 'user' => 'root', 'password' => 'xxx', 'database' => 'test', ]); $result = $mysql->query('SELECT * FROM test_table'); $response->header("Content-Type", "text/plain"); $response->end("Task C executed successfully: " . json_encode($result)); }); break;
如果Task都是CPU密集型操作,协程优化效果有限,这时可以考虑用Swoole的Task Worker进程来分摊计算压力。
2. 如何调用Task参数为taskc的PHP API?
调用方式和普通HTTP请求一致,只需携带Task=taskc参数:
- GET请求:直接访问
http://你的服务器IP:81/?Task=taskc - POST请求:可以通过表单或JSON传递参数,比如用curl命令:
curl -X POST -d "Task=taskc" http://你的服务器IP:81/
也可以用Postman等工具,设置请求参数为Task=taskc即可。
3. Swoole服务器的启动时机是什么?它会自动停止还是持续运行?
Swoole服务器在执行$server->start();时启动,启动后会进入事件循环,持续运行,不会自动停止。停止服务器的方式有:
- 前台运行时,按下终端的
Ctrl+C - 后台运行时,先通过
ps aux | grep 你的脚本文件名找到进程ID,再执行kill 进程ID - 在代码中通过
$server->stop();主动触发停止(比如收到特定信号时)
内容的提问来源于stack exchange,提问作者waleed.makarem
相关产品推荐
相关产品推荐

