實現一個協程版mysql鏈接池

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

<?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();
});
相關文章
相關標籤/搜索