jsp获取连接池的实时连接数_PHP进阶教程-实现一个简单的MySQL连接池
?什么是連接池?
顧名思義,連接池就是一堆預(yù)先創(chuàng)建好的連接,跟容器會有點(diǎn)像。連接池主要是在某種需要網(wǎng)絡(luò)連接的服務(wù),提前把連接建立好存起來,然后存放在一個(gè)池子里面,需要用到的時(shí)候取出來用,用完之后再還回去。
MySQL連接過程
client 建立連接的認(rèn)證過程
- 1、server 監(jiān)聽端口
- 2、client 向server建立TCP連接
- 3、server 向client發(fā)送挑戰(zhàn)碼報(bào)文(報(bào)文詳細(xì)內(nèi)容在下文中有分析)
- 4、client 使用挑戰(zhàn)碼加密密碼,將加密后的密碼包含在回包中,發(fā)送給server
- 5、server 根據(jù)client的回包,驗(yàn)證密碼的有效性,給client發(fā)送ok包或error包
- 6、client發(fā)送SQL執(zhí)行
- 7、關(guān)閉MySQL關(guān)閉、TCP連接
為什么使用連接池?
從圖可以看到想要執(zhí)行一條SQL語句每次都要走 圖:3.5-1都過程,至少要7步才可以成功。MySQL會有連接數(shù)上限的限制,而且每次都執(zhí)行那么多都步驟,頻繁把時(shí)間浪費(fèi)在了網(wǎng)絡(luò)IO上。
沒有連接池的做法類似我們買菜做飯,比如我們要做十個(gè)菜,每做一個(gè)菜就跑一趟菜市場,挑菜、討價(jià)還價(jià)、回家、洗菜、下鍋、起鍋、洗鍋;這樣是不是很浪費(fèi)時(shí)間?那我們想要做十個(gè)菜,提前把這十個(gè)菜的材料都買回來,都洗好備用,然后每次炒都時(shí)候直接下鍋炒就好了。連接池就是提前買好菜,洗好菜(創(chuàng)建連接、驗(yàn)證賬號密碼),在要炒菜的時(shí)候直接下鍋(執(zhí)行SQL)炒。
使用連接池之后,只有在連接池初始化的時(shí)候就進(jìn)行連接然后存到一個(gè)容器里面。每次要執(zhí)行SQL語句的時(shí)候先來這個(gè)池獲取連接對象,然后再發(fā)送SQL語句,當(dāng)SQL語句執(zhí)行完之后,再把這個(gè)連接歸還給連接池。
使用連接池每次執(zhí)行SQL語句只需要執(zhí)行 圖:3.5-1 的第6步就行了,復(fù)用了MySQL連接,在高并發(fā)情況下,節(jié)省了每次連接帶來的其他開銷。
連接池有什么?
- 最小連接數(shù)
- 最大連接數(shù)
- 當(dāng)前連接數(shù)
- 連接池對象
- 獲取連接池超時(shí)時(shí)間
- 健康度檢查
實(shí)戰(zhàn):Swoole實(shí)現(xiàn)連接池
MysqlPool.php
/** * 1、設(shè)置配置信息 * 2、創(chuàng)建連接對象 * 3、獲取連接對象 * 4、獲取連接對象,空閑連接不夠創(chuàng)建到最大連接數(shù) * 5、執(zhí)行sql語句 * 6、歸還連接 */use SwooleCoroutineChannel;class MysqlPool{ // 最小連接數(shù) private $min; // 最大連接數(shù) private $max; // 當(dāng)前連接數(shù) private $count = 0; // 獲取超時(shí)時(shí)間 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); } } /** * 創(chuàng)建數(shù)據(jù)庫連接對象 * @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()); } } /** * 獲取數(shù)據(jù)庫連接 * @return mixed|null|PDO * @throws Exception */ public function getConnection(){ $mysql = null; // 判斷是否為空,如果池空了,判斷當(dāng)前連接數(shù)是否下于最大連接數(shù) // 如果小于最大連接數(shù)創(chuàng)建新連接數(shù) 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); } // 獲取不到數(shù)據(jù)庫連接拋出異常 if (!$mysql) { throw new Exception('沒有連接了'); } // 當(dāng)協(xié)程結(jié)束之后歸還連接池 defer(function () use ($mysql) { $this->connections->push($mysql); }); return $mysql; } /** * 調(diào)試打印連接池的容量,非主要代碼 * @param $str */ public function printLenth($str){ echo $str . $this->connections->length() . ""; }}server.php
include './MysqlPool.php';//創(chuàng)建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();本案例實(shí)現(xiàn):
- 最小連接數(shù)
- 最大連接數(shù)
- 當(dāng)前連接數(shù)
- 連接池對象
- 獲取連接池超時(shí)時(shí)間
思考:怎么實(shí)現(xiàn)健康度檢查?
總結(jié)
以上是生活随笔為你收集整理的jsp获取连接池的实时连接数_PHP进阶教程-实现一个简单的MySQL连接池的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vb.net 设置打印纸张与页边距_文字
- 下一篇: 3d查看器无法加载三维模型_珠峰登顶成功