本文目录导读:

- 使用
go()函数(最常用) - 使用
Swoole\Coroutine::create() - 在Swoole服务器中启用
- 使用
Coroutine\run()函数 - 在Task进程中使用
- 配置协程选项
- 异步单进程模式
- 完整的实际示例
- 注意事项
在Swoole中启动协程主要有以下几种方式,我来详细说明:
使用 go() 函数(最常用)
<?php
// 使用 go() 函数创建协程
go(function () {
// 协程内执行代码
echo "协程1开始\n";
Co::sleep(1); // 模拟异步操作
echo "协程1结束\n";
});
go(function () {
echo "协程2开始\n";
Co::sleep(0.5);
echo "协程2结束\n";
});
echo "主程序\n";
使用 Swoole\Coroutine::create()
<?php
// 使用静态方法创建协程
Swoole\Coroutine::create(function () {
echo "使用静态方法创建协程\n";
Co::sleep(1);
echo "协程完成\n";
});
在Swoole服务器中启用
HTTP服务器
<?php
$http = new Swoole\Http\Server("0.0.0.0", 9501);
$http->on('Request', function ($request, $response) {
// 自动在协程环境中执行
$response->header("Content-Type", "text/plain");
$response->end("Hello World\n");
});
$http->start();
WebSocket服务器
<?php
$ws = new Swoole\WebSocket\Server("0.0.0.0", 9502);
$ws->on('Open', function ($server, $request) {
echo "连接开启\n";
});
$ws->on('Message', function ($server, $frame) {
// 每个消息处理都在协程中
$server->push($frame->fd, "收到: ".$frame->data);
});
$ws->start();
使用 Coroutine\run() 函数
<?php
Swoole\Coroutine\run(function () {
// 在这个闭包中,所有代码都在协程环境中
$result = Swoole\Coroutine\Http\Client::get('http://example.com');
echo $result['body'];
});
在Task进程中使用
<?php
$server = new Swoole\Server("0.0.0.0", 9503);
$server->set([
'task_worker_num' => 4,
]);
$server->on('Receive', function ($server, $fd, $reactor_id, $data) {
$server->task($data);
$server->send($fd, "任务已提交");
});
$server->on('Task', function ($server, $task_id, $reactor_id, $data) {
// Task中自动支持协程
go(function () use ($server, $task_id, $data) {
$result = file_get_contents("http://example.com?id=".$data);
$server->finish($result);
});
});
$server->start();
配置协程选项
<?php
// 设置协程相关配置
Swoole\Coroutine::set([
'max_coroutine' => 100000, // 最大协程数
'stack_size' => 2 * 1024 * 1024, // 栈内存大小
]);
// 或者通过 ini 配置
ini_set('swoole.use_shortname', 'On');
异步单进程模式
<?php
// 创建异步进程
$process = new Swoole\Process(function ($process) {
// 在进程内创建协程
go(function () {
while (true) {
echo "异步进程中的协程\n";
Co::sleep(1);
}
});
}, false);
$process->start();
完整的实际示例
<?php
// 启动协程服务器
class CoroutineServer
{
private $server;
public function __construct()
{
$this->server = new Swoole\Http\Server('0.0.0.0', 9501);
$this->server->set([
'worker_num' => 4,
'enable_coroutine' => true, // 启用协程
'max_coroutine' => 100000, // 最大协程数
'log_level' => 4,
]);
$this->server->on('Request', [$this, 'onRequest']);
$this->server->on('WorkerStart', [$this, 'onWorkerStart']);
}
public function onRequest($request, $response)
{
// 自动运行在协程中
$result = $this->processRequest($request);
$response->end($result);
}
private function processRequest($request)
{
// 模拟异步操作
$data = Co::exec("sleep 1 && echo '处理完成'");
return "结果: " . $data['output'];
}
public function start()
{
echo "协程服务器启动...\n";
$this->server->start();
}
}
(new CoroutineServer())->start();
注意事项
-
必须安装Swoole扩展:
pecl install swoole
-
协程只在异步IO时有效,同步阻塞操作会阻塞整个协程。
-
协程环境:在Swoole服务器中,Worker进程默认就运行在协程环境中。
-
错误处理:
go(function () { try { // 协程代码 } catch (Throwable $e) { echo "错误: " . $e->getMessage(); } });
最常用的就是 go() 函数和服务器事件中自动创建协程,根据你的具体场景选择合适的方式。