一、用途
- 现阶段
Swoole
暂时没有办法hook
所有的阻塞函数,也就意味着有些函数仍然会导致进程阻塞
,从而影响协程的调度。 - 此时我们可以通过使用
Task
组件来模拟协程处理,从而达到不阻塞进程调用阻塞函数的目的。 - 本质上是仍是是多进程运行阻塞函数,所以性能上会明显地不如原生协程,具体取决于
Task Worker
的数量。
二、安装
composer require hyperf/task
三、配置
- 文件:config/autoload/server.php
<?php
use Hyperf\Server\Event;
return [
// 这里省略了其它不相关的配置项
'settings' => [
// Task Worker 数量,根据您的服务器配置而配置适当的数量
'task_worker_num' => 8,
// 因为 `Task` 主要处理无法协程化的方法,所以这里推荐设为 `false`,避免协程下出现数据混淆的情况
'task_enable_coroutine' => false,
],
'callbacks' => [
// Task callbacks
Event::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. 主动方法投递(不推荐)
<?php
use 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()]));