PHP协程用Swoole怎么启

wen PHP项目 2

本文目录导读:

PHP协程用Swoole怎么启

  1. 使用 go() 函数(最常用)
  2. 使用 Swoole\Coroutine::create()
  3. 在Swoole服务器中启用
  4. 使用 Coroutine\run() 函数
  5. 在Task进程中使用
  6. 配置协程选项
  7. 异步单进程模式
  8. 完整的实际示例
  9. 注意事项

在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();

注意事项

  1. 必须安装Swoole扩展

    pecl install swoole
  2. 协程只在异步IO时有效,同步阻塞操作会阻塞整个协程。

  3. 协程环境:在Swoole服务器中,Worker进程默认就运行在协程环境中。

  4. 错误处理

    go(function () {
     try {
         // 协程代码
     } catch (Throwable $e) {
         echo "错误: " . $e->getMessage();
     }
    });

最常用的就是 go() 函数和服务器事件中自动创建协程,根据你的具体场景选择合适的方式。

抱歉,评论功能暂时关闭!