一、用途
- 现阶段
Swoole暂时没有办法hook所有的阻塞函数,也就意味着有些函数仍然会导致进程阻塞,从而影响协程的调度。 - 此时我们可以通过使用
Task组件来模拟协程处理,从而达到不阻塞进程调用阻塞函数的目的。 - 本质上是仍是是多进程运行阻塞函数,所以性能上会明显地不如原生协程,具体取决于
Task Worker的数量。
二、安装
composer require hyperf/task
三、配置
- 文件:config/autoload/server.php
<?phpuse Hyperf\Server\Event;return [// 这里省略了其它不相关的配置项'settings' => [// Task Worker 数量,根据您的服务器配置而配置适当的数量'task_worker_num' => 8,// 因为 `Task` 主要处理无法协程化的方法,所以这里推荐设为 `false`,避免协程下出现数据混淆的情况'task_enable_coroutine' => false,],'callbacks' => [// Task callbacksEvent::ON_TASK => [Hyperf\Framework\Bootstrap\TaskCallback::class, 'onTask'],Event::ON_FINISH => [Hyperf\Framework\Bootstrap\FinishCallback::class, 'onFinish'],],
];
四、使用
1. 使用注解
<?php
namespace App\Service;use Hyperf\Coroutine\Coroutine;
use Hyperf\Task\Annotation\Task;class TaskService
{#[Task]public function handle($cid){return ['worker.cid' => $cid,// task_enable_coroutine 为 false 时返回 -1,反之 返回对应的协程 ID'task.cid' => Coroutine::id(),];}
}
- 调用
<?php
namespace App\Controller;use App\Service\TaskService;
use Hyperf\Coroutine\Coroutine;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;#[AutoController]
class TaskController
{#[Inject]private TaskService $taskService;public function index(RequestInterface $request, ResponseInterface $response){$result = $this->taskService->handle(Coroutine::id());return $response->json($result);}
}
2. 主动方法投递(不推荐)
<?phpuse Hyperf\Coroutine\Coroutine;
use Hyperf\Context\ApplicationContext;
use Hyperf\Task\TaskExecutor;
use Hyperf\Task\Task;class MethodTask
{public function handle($cid){return ['worker.cid' => $cid,// task_enable_coroutine 为 false 时返回 -1,反之 返回对应的协程 ID'task.cid' => Coroutine::id(),];}
}// 使用
$container = ApplicationContext::getContainer();
$exec = $container->get(TaskExecutor::class);
$result = $exec->execute(new Task([MethodTask::class, 'handle'], [Coroutine::id()]));
