本文實例講述了PHP擴展Swoole實現實時異步任務隊列。分享給大家供大家參考,具體如下:
假如要發100封郵件,for循環100遍,用戶直接揭竿而起,什么破網站!
但實際上,我們很可能有超過1萬的郵件。怎么處理這個延遲的問題?
答案就是用異步。把“發郵件”這個操作封裝,然后后臺異步地執行1萬遍。這樣的話,用戶提交網頁后,他所等待的時間只是“把發郵件任務請求推送進隊列里”的時間。而我們的后臺服務將在用戶看不見的地方跑。
在實現“異步隊列”這點上,有人采用MySQL表或者redis來存放待發送的郵件,然后,每分鐘定時讀取待發送列表,然后處理。這便是定時異步任務隊列。但當前提交的任務要一分鐘后才能執行,在某些實時性要求應用場景里還是不快。有些場景要求,只有一提交任務,便馬上執行,但用戶不需要等待返回結果。
本文將探討用php擴展swoole實現實時異步任務隊列的方案。
服務端
在打算放置腳本的目錄(你也可以自行新建)新建Server.php,代碼如下
?php
class Server
{
private $serv;
public function __construct()
{
$this->serv = new swoole_server("0.0.0.0", 9501);
$this->serv->set(array(
'worker_num' => 1, //一般設置為服務器CPU數的1-4倍
'daemonize' => 1, //以守護進程執行
'max_request' => 10000,
'dispatch_mode' => 2,
'task_worker_num' => 8, //task進程的數量
"task_ipc_mode " => 3, //使用消息隊列通信,并設置為爭搶模式
//"log_file" => "log/taskqueueu.log" ,//日志
));
$this->serv->on('Receive', array($this, 'onReceive'));
// bind callback
$this->serv->on('Task', array($this, 'onTask'));
$this->serv->on('Finish', array($this, 'onFinish'));
$this->serv->start();
}
public function onReceive(swoole_server $serv, $fd, $from_id, $data)
{
//echo "Get Message From Client {$fd}:{$data}\n";
// send a task to task worker.
$serv->task($data);
}
public function onTask($serv, $task_id, $from_id, $data)
{
$array = json_decode($data, true);
if ($array['url']) {
return $this->httpGet($array['url'], $array['param']);
}
}
public function onFinish($serv, $task_id, $data)
{
//echo "Task {$task_id} finish\n";
//echo "Result: {$data}\n";
}
protected function httpGet($url, $data)
{
if ($data) {
$url .= '?' . http_build_query($data);
}
$curlObj = curl_init(); //初始化curl,
curl_setopt($curlObj, CURLOPT_URL, $url); //設置網址
curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1); //將curl_exec的結果返回
curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curlObj, CURLOPT_HEADER, 0); //是否輸出返回頭信息
$response = curl_exec($curlObj); //執行
curl_close($curlObj); //關閉會話
return $response;
}
}
$server = new Server();
客戶端
啟動服務后,讓我們看看如何調用服務。新建測試文件Client_test.php
?php
class Client
{
private $client;
public function __construct()
{
$this->client = new swoole_client(SWOOLE_SOCK_TCP);
}
public function connect()
{
if (!$this->client->connect("127.0.0.1", 9501, 1)) {
throw new Exception(sprintf('Swoole Error: %s', $this->client->errCode));
}
}
public function send($data)
{
if ($this->client->isConnected()) {
if (!is_string($data)) {
$data = json_encode($data);
}
return $this->client->send($data);
} else {
throw new Exception('Swoole Server does not connected.');
}
}
public function close()
{
$this->client->close();
}
}
$data = array(
"url" => "http://192.168.10.19/send_mail",
"param" => array(
"username" => 'test',
"password" => 'test'
)
);
$client = new Client();
$client->connect();
if ($client->send($data)) {
echo 'success';
} else {
echo 'fail';
}
$client->close();
在上面代碼中,url即為任務所在地址,param為所需傳遞參數。
保存好代碼,在命令行或者瀏覽器中執行Client_test.php,便實現了異步任務隊列。你所填寫的URL,將會在每次異步任務被提交后,以HTTP GET的方式異步執行。
更多關于PHP相關內容感興趣的讀者可查看本站專題:《PHP擴展開發教程》、《PHP網絡編程技巧總結》、《php curl用法總結》、《PHP數組(Array)操作技巧大全》、《PHP數據結構與算法教程》、《php程序設計算法總結》及《php字符串(string)用法總結》
希望本文所述對大家PHP程序設計有所幫助。
您可能感興趣的文章:- PHP swoole中使用task進程異步的處理耗時任務應用案例分析
- PHP Swoole異步讀取、寫入文件操作示例
- PHP Swoole異步Redis客戶端實現方法示例
- PHP Swoole異步MySQL客戶端實現方法示例
- php基于 swoole 實現的異步處理任務功能示例
- PHP swoole和redis異步任務實現方法分析
- Swoole實現異步投遞task任務案例詳解
- 詳解thinkphp5+swoole實現異步郵件群發(SMTP方式)
- php異步多線程swoole用法實例
- 如何用RabbitMQ和Swoole實現一個異步任務系統