環(huán)境說明: 系統(tǒng):Ubuntu14.04 (安裝教程包括CentOS6.5)
PHP版本:PHP-5.5.10
swoole版本:1.7.6-stable
上一章已經(jīng)簡單介紹了如何寫一個簡單的Echo服務(wù)器,并了解了onReceive等幾個核心回調(diào)函數(shù)的使用方法。這一章,我將介紹如何使用Swoole的異步任務(wù)Task。
Swoole的業(yè)務(wù)邏輯部分是同步阻塞運(yùn)行的,如果遇到一些耗時較大的操作,例如訪問數(shù)據(jù)庫、廣播消息等,就會影響服務(wù)器的響應(yīng)速度。因此Swoole提供了Task功能,將這些耗時操作放到另外的進(jìn)程去處理,當(dāng)前進(jìn)程繼續(xù)執(zhí)行后面的邏輯。
開啟Task功能只需要在swoole_server的配置項(xiàng)中添加task_worker_num一項(xiàng)即可,如下:
$serv->set(array(
'task_worker_num' => 8
));
即可開啟task功能。此外,必須給swoole_server綁定兩個回調(diào)函數(shù):onTask和onFinish。這兩個回調(diào)函數(shù)分別用于執(zhí)行Task任務(wù)和處理Task任務(wù)的返回結(jié)果。
首先是發(fā)起一個Task,代碼如下:
public function onReceive( swoole_server $serv, $fd, $from_id, $data ) {
echo "Get Message From Client {$fd}:{$data}\n";
// send a task to task worker.
$param = array(
'fd' => $fd
);
// start a task
$serv->task( json_encode( $param ) );
echo "Continue Handle Worker\n";
}
可以看到,發(fā)起一個任務(wù)時,只需通過swoole_server對象調(diào)用task函數(shù)即可發(fā)起一個任務(wù)。swoole內(nèi)部會將這個請求投遞給task_worker,而當(dāng)前Worker進(jìn)程會繼續(xù)執(zhí)行。
當(dāng)一個任務(wù)發(fā)起后,task_worker進(jìn)程會響應(yīng)onTask回調(diào)函數(shù),如下:
public function onTask($serv,$task_id,$from_id, $data) {
echo "This Task {$task_id} from Worker {$from_id}\n";
echo "Data: {$data}\n";
for($i = 0 ; $i < 10 ; $i ++ ) {
sleep(1);
echo "Task {$task_id} Handle {$i} times...\n";
}
$fd = json_decode( $data , true )['fd'];
$serv->send( $fd , "Data in Task {$task_id}");
return "Task {$task_id}'s result";
}
這里我用sleep函數(shù)和循環(huán)模擬了一個長耗時任務(wù)。在onTask回調(diào)中,我們通過task_id和from_id(也就是worker_id)來區(qū)分不同進(jìn)程投遞的不同task。當(dāng)一個task執(zhí)行結(jié)束后,通過return一個字符串將執(zhí)行結(jié)果返回給Worker進(jìn)程。Worker進(jìn)程將通過onFinish回調(diào)函數(shù)接收這個處理結(jié)果。
下面來看onFinish回調(diào):
public function onFinish($serv,$task_id, $data) {
echo "Task {$task_id} finish\n";
echo "Result: {$data}\n";
}
在onFinish回調(diào)中,會接收到Task任務(wù)的處理結(jié)果$data。在這里處理這個返回結(jié)果即可。 (Tip:?可以通過在傳遞的data中存放fd、buff等數(shù)據(jù),來延續(xù)投遞Task之前的工作)
之所以在這里講解如何使用swoole_client是因?yàn)?,在寫服?wù)端代碼的時候,不可避免的需要用到客戶端來進(jìn)行測試。swoole提供了swoole_client用于編寫測試客戶端,下面我將講解如何使用這個工具。
swoole_client有兩種工作模式:同步阻塞模式和異步回調(diào)模式。其中,同步阻塞模式在上一章中已經(jīng)給出示例,其使用和一般的socket基本無異。因此,我將重點(diǎn)講解swoole_client的異步回調(diào)模式。
創(chuàng)建一個異步client的代碼如下:
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
其中,SWOOLE_SOCK_ASYNC選項(xiàng)即表明創(chuàng)建一個異步client。
既然是異步,那當(dāng)然需要回調(diào)函數(shù)。swoole_client一共有四個回調(diào)函數(shù),如下:
$client->on("connect", function($cli) {
$cli->send("hello world\n");
});
$client->on("receive", function($cli, $data){
echo "Received: ".$data."\n";
});
$client->on("error", function($cli){
echo "Connect failed\n";
});
$client->on("close", function($cli){
echo "Connection close\n";
});
這幾個回調(diào)函數(shù)的作用基本和swoole_server類似,只有參數(shù)不同,因此不再贅述。?點(diǎn)此查看完整示例
我用swoole擴(kuò)展寫了一個簡單的聊天室Demo(點(diǎn)此查看) 這個Demo雖然用到了一些其他的架構(gòu),但是核心功能仍然是依托swoole擴(kuò)展實(shí)現(xiàn)的。
Server.php是全部的Swoole回調(diào)函數(shù)實(shí)現(xiàn)的類。
更多建議: