我们可以在worker进程中投递一个异步任务到task_worker池中。此函数是非阻塞的,执行完毕会立即返回。worker进程可以继续处理新的请求。
通常会把耗时的任务交给task_worker来处理。
> 我们可以通过如下代码判断是Worker进程还是TaskWorker进程:
```
function onWorkerStart($serv, $worker_id) {
if ($worker_id >= $serv->setting['worker_num']) { //超过worker_num,表示这是一个task进程
}
}
```
看一个示例:
``` php
<?php
$server = new \swoole_server("127.0.0.1",8088);
$server->set(array(
'daemonize' => false,
'reactor_num' => 2,
'worker_num' => 1,
'task_worker_num' => 1,
));
$server->on('start', function ($serv){
swoole_set_process_name("swoole_task_matser"); //主进程命名
});
$server->on('connect', function ($serv, $fd){
echo "client connect. fd is {$fd}\n";
});
$server->on('receive', function ($serv, $fd, $from_id, $data){
echo sprintf("onReceive. fd: %d , data: %s\n", $fd, json_encode($data) );
$serv->task(json_encode([
'fd' => $fd,
'task_name' => 'send_email',
'email_content' => $data,
'email' => 'admin@qq.com'
]));
});
$server->on('close', function ($serv, $fd){
echo "client close. fd is {$fd}\n";
});
$server->on('task', function (swoole_server $serv, $task_id, $from_id, $data){
echo $data;
$data = json_decode($data, true);
$serv->send($data['fd'], "send eamil to {$data['email']}, content is : {$data['email_content']}\n");
//echo 'task finished';
//return 'task finished';
$serv->finish('task finished');
});
$server->on('finish', function (swoole_server $serv, $task_id, $data){
echo 'onFinish:' .$data;
});
$server -> start();
```
这里新建了一个tcp服务器,参数里设置`worker_num`进程为1,`task_worker_num`为1。
配置了`task_worker_num`参数后将会启用task功能,`swoole_server`务必要注册`onTask/onFinish`2个事件回调函数。如果没有注册,服务器程序将无法启动。
onTask回调接收4个参数,分别是serv对象、任务ID、自于哪个worker进程、任务的内容。注意的是,`$data`必须是字符串。我们可以在worker进程里使用`swoole_server->task
($data)`进行任务投递。
onFinish回调用于将处理结果告知worker进程,此回调必须有,但是否被调用由OnTask决定。在OnTask里使用`return`或者`finish()`可以将处理结果发生到onFinish回调,否则onFinish回调是不会被调用的。也就是说:`finish()`是可选的。如果worker进程不关心任务执行的结果,不需要调用此函数。onFinish回调里的`$data`同样必须是字符串。
我们新起一个窗口,使用`telnet`发送消息到服务端进行测试:
client端:
```
telnet 127.0.0.1 8088
Trying 127.0.0.1...
Connected to 127.0.0.1.
hhh
send eamil to admin@qq.com, content is : hhh
```
server端:
```
client connect. fd is 1
onReceive. fd: 1 , data: "hhh\r\n"
{"fd":1,"task_name":"send_email","email_content":"hhh\r\n","email":"admin@qq.com"}
onFinish:task finished
```
onFinish回调里不使用`return`或者`finish()`,我们将看不到server端最后一行输出。
此时服务器进程模型:
```
pstree -ap | grep swoole
| | `-php,3190 swoole_task.php
| | |-php,3192 swoole_task.php
| | | |-php,3194 swoole_task.php
| | | `-php,3195 swoole_task.php
```
看到两个worker进程,其中一个是worker进程,另外一个是task_worker进程。