我們可以在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進程。