實現一個協程版的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(); });