日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

什么是連接池?

顧名思義,連接池就是一堆預先創建好的連接,跟容器會有點像。連接池主要是在某種需要網絡連接的服務,提前把連接建立好存起來,然后存放在一個池子里面,需要用到的時候取出來用,用完之后再還回去。

MySQL連接過程

client 建立連接的認證過程

  • 1、server 監聽端口
  • 2、client 向server建立TCP連接
  • 3、server 向client發送挑戰碼報文(報文詳細內容在下文中有分析)
  • 4、client 使用挑戰碼加密密碼,將加密后的密碼包含在回包中,發送給server
  • 5、server 根據client的回包,驗證密碼的有效性,給client發送ok包或error包
  • 6、client發送SQL執行
  • 7、關閉MySQL關閉、TCP連接
PHP進階教程-實現一個簡單的MySQL連接池

 

為什么使用連接池?

PHP進階教程-實現一個簡單的MySQL連接池

 

從圖可以看到想要執行一條SQL語句每次都要走 圖:3.5-1都過程,至少要7步才可以成功。MySQL會有連接數上限的限制,而且每次都執行那么多都步驟,頻繁把時間浪費在了網絡IO上。

沒有連接池的做法類似我們買菜做飯,比如我們要做十個菜,每做一個菜就跑一趟菜市場,挑菜、討價還價、回家、洗菜、下鍋、起鍋、洗鍋;這樣是不是很浪費時間?那我們想要做十個菜,提前把這十個菜的材料都買回來,都洗好備用,然后每次炒都時候直接下鍋炒就好了。連接池就是提前買好菜,洗好菜(創建連接、驗證賬號密碼),在要炒菜的時候直接下鍋(執行SQL)炒。

PHP進階教程-實現一個簡單的MySQL連接池

 

使用連接池之后,只有在連接池初始化的時候就進行連接然后存到一個容器里面。每次要執行SQL語句的時候先來這個池獲取連接對象,然后再發送SQL語句,當SQL語句執行完之后,再把這個連接歸還給連接池。

使用連接池每次執行SQL語句只需要執行 圖:3.5-1 的第6步就行了,復用了MySQL連接,在高并發情況下,節省了每次連接帶來的其他開銷。

連接池有什么?

  • 最小連接數
  • 最大連接數
  • 當前連接數
  • 連接池對象
  • 獲取連接池超時時間
  • 健康度檢查

實戰:Swoole實現連接池

MysqlPool.php

/**
 * 1、設置配置信息
 * 2、創建連接對象
 * 3、獲取連接對象
 * 4、獲取連接對象,空閑連接不夠創建到最大連接數
 * 5、執行sql語句
 * 6、歸還連接
 */

use SwooleCoroutineChannel;

class MysqlPool
{
    // 最小連接數
    private $min;
    // 最大連接數
    private $max;
    // 當前連接數
    private $count = 0;
    // 獲取超時時間
    private $timeOut = 0.2;
    // 連接池對象容器
    private $connections;
    // 配置信息
    private $config = [];
    // 連接池對象
    private static $instance;
    public function __construct(array $config){
        $this->config = $config;
        $this->min = $this->config['min'] ?? 2;
        $this->max = $this->config['max'] ?? 4;
        $this->timeOut = $this->config['time_out'] ?? 0.2;
        $this->connections = new Channel($this->max);
    }

    /**
     * 獲取連接池對象
     * @param null $config
     * @return MysqlPool
     */
    public static function getInstance($config = null){
        if (empty(self::$instance)) {
            if (empty($config)) {
                throw new RuntimeException("mysql config empty");
            }
            self::$instance = new static($config);
        }

        return self::$instance;
    }

    /**
     * 初始化連接池
     * @throws Exception
     */
    public function init(){
        for ($i = 0; $i < $this->min; $i++) {
            $this->count++;
            $mysql = $this->createDb();
            $this->connections->push($mysql);
        }

    }

    /**
     * 創建數據庫連接對象
     * @return PDO
     * @throws Exception
     */
    private function createDb(){
        $dsn = "mysql:dbname={$this->config['database']};host={$this->config['db_host']}";
        try {
            $mysql = new PDO($dsn, $this->config['db_user'], $this->config['db_passwd']);
            return $mysql;
        } catch (PDOException $e) {
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 獲取數據庫連接
     * @return mixed|null|PDO
     * @throws Exception
     */
    public function getConnection(){
        $mysql = null;
        // 判斷是否為空,如果池空了,判斷當前連接數是否下于最大連接數
        // 如果小于最大連接數創建新連接數
        if ($this->connections->isEmpty()) {
            if ($this->count < $this->max) {
                $this->count++;
                $mysql = $this->createDb();
            } else {
                $mysql = $this->connections->pop($this->timeOut);
            }
        } else {
            $mysql = $this->connections->pop($this->timeOut);
        }
        // 獲取不到數據庫連接拋出異常
        if (!$mysql) {
            throw new Exception('沒有連接了');
        }
        // 當協程結束之后歸還連接池
        defer(function () use ($mysql) {
            $this->connections->push($mysql);
        });
        return $mysql;
    }

    /**
     * 調試打印連接池的容量,非主要代碼
     * @param $str
     */
    public function printLenth($str){
        echo $str . $this->connections->length() . "n";
    }
}

server.php

include './MysqlPool.php';
//創建http server
$http = new SwooleHttpServer("0.0.0.0", 9501);
$http->set(["worker_num" => 2]);
$http->on('WorkerStart', function ($serv, $worker_id) {
    $config = [
        'min' => 3,
        'max' => 5,
        'time_out' => 1,
        'db_host' => '127.0.0.1',
        'db_user' => 'root',
        'db_passwd' => 'sunny123',
        'database' => 'lv'
    ];
    MysqlPool::getInstance($config)->init();
});

$http->on('request', function ($request, $response) {
    try {
        MysqlPool::getInstance()->printLenth(SwooleCoroutine::getCid() . '獲取前:');
        $mysql = MysqlPool::getInstance()->getConnection();
        MysqlPool::getInstance()->printLenth(SwooleCoroutine::getCid() . '歸還前:');
        $result = $mysql->query("select * from sunny_member");
        $row = $result->fetch(MYSQLI_ASSOC);
        MysqlPool::getInstance()->printLenth(SwooleCoroutine::getCid() . '歸還后:');
        $response->end($row['content']);
    } catch (Exception $e) {
        $response->end($e->getMessage());
    }
});
$http->start();

本案例實現:

  • 最小連接數
  • 最大連接數
  • 當前連接數
  • 連接池對象
  • 獲取連接池超時時間

思考:怎么實現健康度檢查?

分享到:
標簽:連接池 MySQL
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定