天天看点

Swoole来实现实时异步任务队列

假如要发100封邮件,for循环100遍,用户直接揭竿而起,什么破网站!

但实际上,我们很可能有超过1万的邮件。怎么处理这个延迟的问题?

答案就是用异步。把“发邮件”这个操作封装,然后后台异步地执行1万遍。这样的话,用户提交网页后,他所等待的时间只是“把发邮件任务请求推送进队列里”的时间。而我们的后台服务将在用户看不见的地方跑。

本文将探讨用php扩展swoole实现实时异步任务队列的方案。

在打算放置脚本的目录(你也可以自行新建)新建server.php,代码如下

Swoole来实现实时异步任务队列

<?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

Swoole来实现实时异步任务队列

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