Swoole怎么异步执行一个耗时任务_技术学院_宜昌市隼壹珍商贸有限公司

您好,欢迎访问宜昌市隼壹珍商贸有限公司

400 890 5375
当前位置: 主页 > 新闻动态 > 技术学院

Swoole怎么异步执行一个耗时任务

发布时间:2025-10-05  |  点击率:
Swoole通过Task Worker、Process和协程实现异步任务处理。在Web服务中推荐使用Task Worker,将耗时任务如发邮件、数据导入等投递至task进程异步执行,避免阻塞主进程;可通过task()方法提交任务,在on('task')中处理,完成后触发on('finish')回调。对于非服务器场景,可使用Swoole\Process创建独立子进程执行任务,并通过Process::wait()回收防止僵尸进程。在协程环境下,可使用Co::exec执行外部命令,虽为同步执行但不阻塞其他协程,真正异步仍需结合task或进程。根据环境选择合适方式:Web用Task Worker,常驻脚本用Process,协程轻量操作用Co::exec。

Swoole 提供了多种方式来异步执行耗时任务,避免阻塞主进程或协程,提升服务响应性能。最常用的方式是使用 异步进程(Process)Task Worker 来处理耗时操作,比如发送邮件、写日志、数据导入导出等。

使用 Task Worker 异步处理任务

这是 Swoole 中推荐的做法,适用于 HTTP 服务器、WebSocket 服务器等场景。

在 Swoole 服务器中开启 task worker,将耗时任务投递到 task 进程中异步执行。

示例代码:

启动一个支持 task 的 Swoole 服务器:

$http = new Swoole\Http/Server("127.0.0.1", 9501);

// 设置 task 工作进程数量
$http->set([
    'task_worker_num' => 4,
]);

// 处理普通请求
$http->on('request', function ($request, $response) use ($http) {
    if (isset($request->post['action']) && $request->post['action'] == 'slow_task') {
        // 投递一个耗时任务
        $taskID = $http->task("模拟一个耗时任务,比如发送邮件");
        $response->end("任务已提交,ID: {$taskID}");
    } else {
        $response->end("Hello Swoole");
    }
});

// 处理任务(在 task 进程中执行)
$http->on('task', function ($server, $task) {
    // 模拟耗时操作
    sleep(5); // 实际中可能是调用 API、写文件、发短信等
    echo "任务完成:{$task->data}\n";

    // 可以返回结果给 finish 回调
    $server->finish("任务 {$task->id} 完成");
});

// 任务完成后的回调(可选)
$http->on('finish', function ($server, $taskID, $data) {
    echo "任务 {$taskID} 的结果:{$data}\n";
});

$http->start();

说明:

  • task() 方法会把任务数据交给一个空闲的 task 进程异步执行。
  • on('task') 是任务实际执行的地方,不会影响主 Reactor 线程。
  • on('finish') 接收任务完成的通知,适合做后续处理。

使用 Swoole Process 创建独立异步进程

如果你不需要集成到服务器中,也可以手动创建子进程来异步执行任务。

$process = new Swoole\Process(function (Swoole\Process $worker) {
    // 子进程中执行耗时任务
    sleep(3);
    file_put_contents('/tmp/async.log', "任务完成时间:" . date('Y-m-d H:i:s') . "\n", FILE_APPEND);
    $worker->exit(0);
}, false, false);

$pid = $process->start();
echo "异步任务已启动,PID: {$pid}\n";

// 不等待,继续执行其他逻辑

你还可以通过 Process::wait() 在主进程回收子进程,防止僵尸进程。

协程环境下异步执行(Co::exec 或 go())

在 Swoole 协程环境中,如果只是“非阻塞”执行外部命令,可以使用 Co::exec

go(function () {
    $result = Co::exec("python /scripts/data_process.py"); // 执行脚本
    echo "脚本输出:{$result['output']}";
});
// 主协程继续执行,不阻塞

注意:这仍然是同步执行该命令,但放在协程里不会阻塞其他协程。若要真正异步,建议结合进程或 task 使用。

基本上就这些常用方式。根据你的运行环境选择:

  • Web 服务中用 Task Worker 最合适。
  • 常驻脚本可用 Swoole\Process
  • 协程内轻量操作可用 Co::exec 配合调度。

全国统一服务电话

400 890 5375

电子邮箱:879577@qq.com

公司地址:宜昌市西陵区黄河路5号三峡明珠10栋1051室

咨询微信

TEL:13680874598