天天看點

swoole mysql 連接配接池

懵懵懂懂的 去年開始接觸一部分java程式員 才知道程序的概念 單程序的php 在mysql沒有連接配接池的情況下  确實慢了很多

于是查詢了半天 找到了韓天峰大神開發的 swoole ,敬仰10分鐘 感覺 好多困擾自己的問題 一下就解決了 包括之前的 多程序發郵件 http://blog.csdn.net/zhaodongku/article/details/79570428 

今天找了片文章,特别感謝 @水晶依戀 的http://blog.csdn.net/qq_28602957/article/details/78305039 

自己也搭建了下

測試說明 已經提前往資料庫添加 id 和num 字段 num字段為随機數 1111-9999  

添加了 一共20萬條資料,然後分别用swoole的簡單連接配接池 和 mysql 直接去查詢資料,然後 json_encode(資料).time 來對比查詢效率

client.php

$client = new swoole_client(SWOOLE_SOCK_TCP);//建立swoole tcp用戶端

$client->connect('127.0.0.1', 9503, 10) or die("連接配接失敗");//連接配接server

$num=rand(1111,9999);

echo  $sql = "SELECT * FROM `test`  where num  =  $num ;";

$client->send($sql);

$data = $client->recv();

$time=date("Y-m-d H:i:s",time());

$data=json_encode($data).$time; 

file_put_contents("./test.txt", $data.PHP_EOL, FILE_APPEND);

$client->close();

my.php(普通mysqli查詢)

$conn = @mysqli_connect("127.0.0.1", "root", "root", "lingchen");

$num=rand(1111,9999);

echo  $sql = "SELECT * FROM `test`  where num  =  $num ;";

if($conn){

    //mysqli_select_db($conn,"hulk");

    $res=mysqli_query($conn,$sql);

    $row=mysqli_fetch_assoc($res);

    $time=date("Y-m-d H:i:s",time());

$data=json_encode($row).$time; 

file_put_contents("./test1.txt", $data.PHP_EOL, FILE_APPEND);

}else{

    echo "ERROR";

}

在伺服器   php server.php 可以列印一些資訊

server.php

<?php

$serv = new swoole_server('127.0.0.1', 9503);

$serv->set(array(

    'worker_num' => 20, //worker程序數量

    'task_worker_num' => 10, //task程序數量 即為維持的MySQL連接配接的數量

));

echo 111;

function my_onReceive($serv, $fd, $from_id, $data)

{

    echo "收到資料".$data.PHP_EOL;

    //taskwait就是投遞一條任務,這裡直接傳遞SQL語句了

    //然後阻塞等待SQL完成,并傳回結果

    $result = $serv->taskwait($data);

    echo "任務結束".PHP_EOL;

    if ($result !== false) {

        list($status, $db_res) = explode(':', $result, 2);

        if ($status == 'OK') {

            //資料庫操作成功了,執行業務邏輯代碼,這裡就自動釋放掉MySQL連接配接的占用

            //将處理結果發送給用戶端

            $serv->send($fd, var_export(unserialize($db_res), true) . "\n");

        } else {

            $serv->send($fd, $db_res);

        }

        return;

    } else {

        $serv->send($fd, "Error. Task timeout\n");//如果傳回的是false,則說明taskwait等待逾時,可以設定相應的等待逾時時間

    }

}

function my_onTask($serv, $task_id, $from_id, $sql)

{

    echo "開始做任務 task id:".$task_id.PHP_EOL;

    static $link = null;

    HELL:

    if ($link == null) {

       $link = @mysqli_connect("127.0.0.1", "root", "root", "lingchen");

        if (!$link) {

            $link = null;

            $serv->finish("ER:" . mysqli_error($link));

            return;

        }   

    }   

    $result = $link->query($sql);

    if (!$result) { //如果查詢失敗了

        if(in_array(mysqli_errno($link), [2013, 2006])){//錯誤碼為2013,或者2006,則重連資料庫,重新執行sql

                $link = null;

                goto HELL;

        }else{

            $serv->finish("ER:" . mysqli_error($link));

            return;

        }

    }

    if(preg_match("/^select/i", $sql)){//如果是select操作,就傳回關聯數組

        $data = $result->fetch_assoc();

    }else{//否則直接傳回結果

        $data = $result;

    }

    $serv->finish("OK:" . serialize($data));//調用finish方法,用于在task程序中通知worker程序,投遞的任務已完成

    //return "OK:".serialize($data);

}

function my_onFinish($serv, $task_id, $data)

{

    echo "任務完成";//taskwait 沒有觸發這個函數。。

    echo "AsyncTask Finish:Connect.PID=" . posix_getpid() . PHP_EOL;

}

$serv->on('receive', 'my_onReceive');

$serv->on('task', 'my_onTask');

$serv->on('Finish', 'my_onFinish');

$serv->start();//啟動server

測試工具 ab

請求次數 5000次

結果:

單程序php                             17:18:37  17:21:32    不到2分55

mysql連接配接池                           17:17:21   17:18:06  45秒   

                                            17:23:49  17:24:21   32秒  

                  一萬條請求            17:48:46   17:49:48