实现一个协程版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();
});
本人博客所有文章,均为原创。部分文章中或引用相关资料,但均已著明来源出处。可随意转载、分享,但需加本文链接,以及版权说明。