假如要發100封郵件,for循環100遍,使用者直接揭竿而起,什麼破網站!
但實際上,我們很可能有超過1萬的郵件。怎麼處理這個延遲的問題?
答案就是用異步。把“發郵件”這個操作封裝,然後背景異步地執行1萬遍。這樣的話,使用者送出網頁後,他所等待的時間隻是“把發郵件任務請求推送進隊列裡”的時間。而我們的背景服務将在使用者看不見的地方跑。
本文将探讨用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

class client
private $client;
$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的方式異步執行。