天天看點

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的方式異步執行。