實現一個協程版mysql連接池


實現一個協程版的mysql連接池,該連接池支持自動創建最小連接數,自動檢測mysql健康;基於swoole的chanel。
最近事情忙,心態也有點不積極。技術倒是沒有落下,只是越來越不想寫博客了。想到平時自己上網上找資料的痛苦,於是將自己這篇連接池的文章放出來,給需要的程序員一點幫助。

<?php

/**
 * 實現一個協程版的mysql 連接池
 * Created by PhpStorm.
 * User: roverliang
 * Date: 2018/12/10
 * Time: 23:27
 */

namespace console\libs;

use Swoole\Coroutine\MySQL as coMysql;
use Swoole\Coroutine\Channel;

class CoMysqlPool extends coMysql
{
    protected $maxNums;   //最大連接數
    protected $minNums;   //最小連接數
    protected $mysqlConfig = array(
        'host'     => '127.0.0.1',
        'port'     => 3306,
        'user'     => 'root',
        'password' => '',
        'database' => 'hifuli',
        'timeout'  => -1,
    );  //mysql配置
    protected $chan;      //channel
    protected $currentConnectedNums;  //當前連接數
    protected $tag;       //標識

    /**
     * 初始化連接池
     * CoMysqlPool constructor.
     * @param int $maxNums 最大連接數
     * @param int $minNums 最小連接數
     * @param array $mysqlConfig mysql配置
     */
    public function __construct($maxNums = 20, $minNums = 5, $mysqlConfig = [])
    {
        $this->maxNums = $maxNums;
        $this->minNums = $minNums;
        if (!empty($mysqlConfig) && is_array($mysqlConfig)) {
            $this->mysqlConfig = $mysqlConfig;
        }
        $this->chan = new Channel($maxNums);
        $this->tag  = true;
    }


    /**
     * 從連接池中獲取一個mysql連接對象
     * Created by 梁子(roverliang) <mr.roverliang@gmail.com>
     * 2018/12/10
     */
    public function pop()
    {
        if (!$this->tag) return false;

        if ($mysql = $this->getMysqlInstance()) {
            echo "創建了一個mysql".PHP_EOL;
            return $mysql;
        }

        $mysql = $this->chan->pop();
        if (!$this->checkMysqlHealth($mysql)) {
            $mysql = $this->getMysqlInstance();
        } else {
            echo "復用mysql".PHP_EOL;
        }
        return $mysql;
    }


    /**
     * 將mysql對象放回連接池
     * Created by 梁子(roverliang) <mr.roverliang@gmail.com>
     * 2018/12/10
     * @param $obj
     */
    public function push($mysql)
    {
        if (!$this->tag) return false;
        if (!$this->chan->isFull()) {
            echo "將mysql放入連接池".PHP_EOL;
            $this->chan->push($mysql);
        }
        return true;
    }


    /**
     * 獲取mysql實例
     * Created by 梁子(roverliang) <mr.roverliang@gmail.com>
     * 2018/12/10
     * @return bool
     */
    protected function getMysqlInstance()
    {
        if (!$this->chan->isFull()) {
            $mysqlInstance = new \Swoole\Coroutine\MySQL();
            $mysqlInstance->connect($this->mysqlConfig);
            return $mysqlInstance;
        }
        return false;
    }


    /**
     * 檢測mysql連接是否健康
     * Created by 梁子(roverliang) <mr.roverliang@gmail.com>
     * 2018/12/10
     */
    protected function checkMysqlHealth($mysql)
    {
        if (!$mysql->connected) return false;
        return true;
    }


    /**
     * 銷毀連接池
     * Created by 梁子(roverliang) <mr.roverliang@gmail.com>
     * 2018/12/11
     */
    public function destroyPool()
    {
        $this->tag = false;
        while ($this->chan->length()) {
            $mysql = $this->chan->pop();
            $mysql->close();
            echo "銷毀mysql".PHP_EOL;
        }
        return true;
    }


    /**
     * 監控進程池
     * Created by Roverliang.
     * Date: 2018/12/12 Time: 17:12
     */
    public function monitorPool()
    {
        declare(ticks=10);
        $self = $this;
        register_tick_function(function () use ($self) {
            if (($self->chan->length() < $self->minNums) && $self->tag) {
                $mysql = $self->pop();
                if ($self->checkMysqlHealth($mysql)) {
                    echo "mysql進程監控池自動創建mysql".PHP_EOL;
                    $self->push($mysql);
                }
            }
        });
    }

}



go(function(){
    $mysqlPool = new CoMysqlPool(10, 2);
    $mysqlPool->monitorPool();

    for($i=0; $i<20;$i++) {
        $mysqlPool->monitorPool();
        $mysql = $mysqlPool->pop();
        $mysqlPool->push($mysql);
        \Swoole\Coroutine::sleep(1);
    }

    $mysqlPool->destroyPool();
});


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM