假如要发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的方式异步执行。