
Swoole 作为 PHP 的高性能扩展,在底层封装了一个高效的异步非阻塞网络 I/O 服务器(基于 epoll/kqueue 等多路复用机制),并支持多进程/多线程模型。
这让 PHP 开发者可以专注于业务逻辑(如事件回调处理),而无需纠结底层 I/O 细节。相比纯异步框架如 Nginx(事件驱动静态服务器)、Tornado(Python 的异步 Web 框架)或 Node.js(单线程事件循环),Swoole 的最大亮点在于其混合模式:既能全异步运行,又能通过协程实现“伪同步”编程。这大大降低了并发开发的门槛,同时保持高性能。
多进程模型 server.php
<?php
/**
* @desc 多进程模型(Master-Worker 模式)
* @author Tinywan(ShaoBo Wan)
*/
declare(strict_types=1);
$server = new Swoole\Server('0.0.0.0', 9501);
// 配置进程数
$server->set([
'worker_num' => 4,// 4个Worker进程
'reactor_num' => 2,// 2个Reactor线程
'task_worker_num' => 2// 2个Task进程
]);
//监听连接进入事件。
$server->on('Connect', function ($server, $fd) {
echo"[0] Client: Connect.\n";
});
// Worker进程处理请求(监听数据接收事件)
$server->on('receive', function ($server, $fd, $reactor_id, $data) {
//投递异步任务
$task_id = $server->task($data);
echo"[1] Dispatch AsyncTask: id={$task_id}\n";
return $server->send($fd, "Server: {$data}");
});
// Task进程处理耗时任务。处理异步任务(此回调函数在task进程中执行)
$server->on('task', function ($serv, $task_id, $reactor_id, $data) {
sleep(3);// 模拟耗时操作
echo"[2] New AsyncTask[id={$task_id}]" . PHP_EOL;
//返回任务执行的结果
$serv->finish("{$data} -> OK");
});
//处理异步任务的结果(此回调函数在worker进程中执行)。
$server->on('Finish', function ($serv, $task_id, $data) {
echo"[3] AsyncTask[{$task_id}] Finish: {$data}" . PHP_EOL;
});
$server->start();
执行程序(推荐使用 swoole-cli)
swoole-cli.exe server.php
在命令行下运行 server.php 程序,启动成功后可以使用 netstat 工具看到已经在监听 9501 端口。
使用 telnet/netcat 工具连接服务器。
telnet 127.0.0.1 9501
进入命令模式 ctrl + ](用windows下的telnet登录到该端口的时候,每按一个键就会发送到socket中去)
欢迎使用 Microsoft Telnet Client
Escape 字符为 'CTRL+]'
Microsoft Telnet> send Hello
发送字符串 Hello
Microsoft Telnet> send Tinywan
发送字符串 Tinywan
执行程序打印信息
swoole-cli.exe server.php
[0] Client: Connect.
[1] Dispatch AsyncTask: id=0
[2] New AsyncTask[id=0]
[3] AsyncTask[0] Finish: Hello -> OK
[1] Dispatch AsyncTask: id=1
[2] New AsyncTask[id=1]
[3] AsyncTask[1] Finish: Tinywan -> OK
在 Swoole(或类似事件驱动框架)中,异步 I/O 的核心是非阻塞操作 + 事件通知,避免了传统阻塞 I/O 的线程/进程等待开销。底层依赖操作系统提供的 I/O 多路复用(如 epoll),结合用户态事件循环,实现高效的“就绪再处理”。
// 一键开启协程Hook
Swoole\Runtime::enableCoroutine();
// 异步文件读取(非阻塞)
$content = file_get_contents("large_file.txt");
var_dump($content);
协程化 I/O
go(function () {
// 协程HTTP请求
$http = new Swoole\Coroutine\Http\Client('tinywan.com', 80);
$http->get('/api/webman');
echo $http->body;
});
use Swoole\Coroutine\Client;go(function () {
$client = new Client(SWOOLE_SOCK_TCP);
if (!$client->connect('127.0.0.1', 9501, 0.5)) {
echo"connect failed. Error: {$client->errCode}\n";
}
// 并发发送100个请求
for ($i = 1; $i <= 100; $i++) {
$client->send("hello world\n");
Co::sleep(0.1);// 模拟间隔
}
echo $client->recv();
$client->close();
});
declare(strict_types=1);
$http = new Swoole\Http\Server('0.0.0.0', 9501);
$http->on('Request', function ($request, $response) {
// 异步MySQL查询
$mysql = new mysqli('127.0.0.1', 'root', '123456', 'nacos', 3308);
var_dump($mysql);
// 并发执行多个查询
$results = [
'user' => $mysql->query('SELECT * FROM users LIMIT 10')->fetch_assoc(),
'product' => $mysql->query('SELECT * FROM tenant_info LIMIT 5')->fetch_assoc()
];
$response->header('Content-Type', 'text/html; charset=utf-8');
$response->end(json_encode($results));
});
$http->start();