摘要:概述這是關于入門學習的第八篇文章連接池的實現。開始今天的文章,這篇文章實現了連接池,代碼是在的實現文章的基礎上進行開發的。
概述
這是關于 Swoole 入門學習的第八篇文章:Swoole MySQL 連接池的實現。
第七篇:Swoole RPC 的實現
第六篇:Swoole 整合成一個小框架
第五篇:Swoole 多協議 多端口 的應用
第四篇:Swoole HTTP 的應用
第三篇:Swoole WebSocket 的應用
第二篇:Swoole Task 的應用
第一篇:Swoole Timer 的應用
收到讀者的咨詢,這情況大家可能也會有,所以就在這說說:
“亮哥,我今年30歲了,有點中年危機,最近有點焦慮,發現工作雖然很忙,但是沒感覺能力有所提升,整天都有寫不完的業務代碼,時間緊有時代碼質量也不怎么樣,知道還有很多改進空間,但一直沒時間改,主要是后面項目壓著,馬上又要進入開發了,這種情況怎么辦?”
首先,我是菜雞,觀點不喜勿噴,那我就說下自己的看法:
上面的描述比較主觀,人呀有時候發現不了自己的能力很正常,有時候有能力了并不是馬上就能顯現的,而是到了某個階段后突然發現,哇塞,原來自己這么厲害。
當然能力也分很多種,比如專業能力,快速學習能力,進度把控能力,還有自信也是一種能力,不要臉是一種能力,堅持不要臉更是一種能力。
其實能力提升最快的還是靠工作實踐,悄悄問問自己加入了很多大牛的微信群,能力提升了嗎?看書自學不實踐是不是吸收的也不多。
如果非要給一個具體的方案,那就是在團隊內多分享吧,因為在分享前你會做充分的準備來避免分享時出丑,即使有時候自己知道,當講出來的時候就不是那么回事了。
前期分享可以是看稿,后期練習無稿分享。
然后,再多說一點,30了給自己一個目標,不要盲目每天就是學學學,比如目標是技術專家,目標是業務專家,都很好呀,當然目標與自己性格有關也不是一成不變的。
圍繞著目標設置一些計劃,不要以為每天的學學學,就覺得其他的一切就自然而來,其中還有很多機遇和人脈的因素。
最后,如果實在感覺壓得喘不過氣,就換個環境吧,別和自己過不去。
開始今天的文章,這篇文章實現了 Swoole MySQL 連接池,代碼是在《Swoole RPC 的實現》文章的基礎上進行開發的。
先回顧上篇文章的內容:
實現了 HTTP / TCP 請求
實現了 同步 / 異步 請求
分享了 OnRequest.php、OnReceive.php 源碼
業務邏輯 Order.php 中返回的是假數據
本篇文章主要的功能點:
業務邏輯 Order.php 中返回 MySQL 數據庫中的數據。
Task 啟用了協程
支持 主/從 數據庫配置
實現數據庫連接池
實現數據庫 CURD
代碼 Order.phpmysql = $pool->get(); $this->table = "order"; } public function add($code = "", $name = "") { //TODO 驗證 return $this->mysql->insert($this->table, ["code" => $code, "name" => $name]); } public function edit($id = 0, $name="") { //TODO 驗證 return $this->mysql->update($this->table, ["name" => $name], ["id" => $id]); } public function del($id = 0) { //TODO 驗證 return $this->mysql->delete($this->table, ["id" => $id]); } public function info($code = "") { //TODO 驗證 return $this->mysql->select($this->table, ["code" => $code]); } }Task 啟用協程
一、需要新增兩項配置:
enable_coroutine = true task_enable_coroutine = true
二、回調參數發生改變
$serv->on("Task", function ($serv, $task_id, $src_worker_id, $data) { ... }); 修改成: $serv->on("Task", function ($serv, $task) { $task->worker_id; //來自哪個`Worker`進程 $task->id; //任務的編號 $task->data; //任務的數據 });數據庫 主/從 配置
Mysql.php
數據庫連接池MysqlPool.php
pool)) { $this->config = $config; $this->pool = new chan($config["master"]["pool_size"]); for ($i = 0; $i < $config["master"]["pool_size"]; $i++) { go(function() use ($config) { $mysql = new MysqlDB(); $res = $mysql->connect($config); if ($res === false) { throw new RuntimeException("Failed to connect mysql server"); } else { $this->pool->push($mysql); } }); } } } public function get() { if ($this->pool->length() > 0) { $mysql = $this->pool->pop($this->config["master"]["pool_get_timeout"]); if (false === $mysql) { throw new RuntimeException("Pop mysql timeout"); } defer(function () use ($mysql) { //釋放 $this->pool->push($mysql); }); return $mysql; } else { throw new RuntimeException("Pool length <= 0"); } } }數據庫 CURDMysqlDB.php
_execute($arguments[0]); } } public function connect($config) { //主庫 $master = new SwooleCoroutineMySQL(); $res = $master->connect($config["master"]); if ($res === false) { throw new RuntimeException($master->connect_error, $master->errno); } else { $this->master = $master; } //從庫 $slave = new SwooleCoroutineMySQL(); $res = $slave->connect($config["slave"]); if ($res === false) { throw new RuntimeException($slave->connect_error, $slave->errno); } else { $this->slave = $slave; } $this->config = $config; return $res; } public function insert($table = "", $data = []) { $fields = ""; $values = ""; $keys = array_keys($data); foreach ($keys as $k) { $fields .= "`".addslashes($k)."`, "; $values .= """.addslashes($data[$k])."", "; } $fields = substr($fields, 0, -2); $values = substr($values, 0, -2); $sql = "INSERT INTO `{$table}` ({$fields}) VALUES ({$values})"; return $this->_execute($sql); } public function update($table = "", $set = [], $where = []) { $arr_set = []; foreach ($set as $k => $v) { $arr_set[] = "`".$k . "` = " . $this->_escape($v); } $set = implode(", ", $arr_set); $where = $this->_where($where); $sql = "UPDATE `{$table}` SET {$set} {$where}"; return $this->_execute($sql); } public function delete($table = "", $where = []) { $where = $this->_where($where); $sql = "DELETE FROM `{$table}` {$where}"; return $this->_execute($sql); } public function select($table = "",$where = []) { $where = $this->_where($where); $sql = "SELECT * FROM `{$table}` {$where}"; return $this->_execute($sql); } private function _where($where = []) { $str_where = ""; foreach ($where as $k => $v) { $str_where .= " AND `{$k}` = ".$this->_escape($v); } return "WHERE 1 ".$str_where; } private function _escape($str) { if (is_string($str)) { $str = """.$str."""; } elseif (is_bool($str)) { $str = ($str === FALSE) ? 0 : 1; } elseif (is_null($str)) { $str = "NULL"; } return $str; } private function _execute($sql) { if (strtolower(substr($sql, 0, 6)) == "select") { $db = $this->_get_usable_db("slave"); } else { $db = $this->_get_usable_db("master"); } $result = $db->query($sql); if ($result === true) { return [ "affected_rows" => $db->affected_rows, "insert_id" => $db->insert_id, ]; } return $result; } private function _get_usable_db($type) { if ($type == "master") { if (!$this->master->connected) { $master = new SwooleCoroutineMySQL(); $res = $master->connect($this->config["master"]); if ($res === false) { throw new RuntimeException($master->connect_error, $master->errno); } else { $this->master = $master; } } return $this->master; } elseif ($type == "slave") { if (!$this->slave->connected) { $slave = new SwooleCoroutineMySQL(); $res = $slave->connect($this->config["slave"]); if ($res === false) { throw new RuntimeException($slave->connect_error, $slave->errno); } else { $this->slave = $slave; } } return $this->slave; } } }OnWorkerStart 中調用try { MysqlPool::getInstance(get_config("mysql")); } catch (Exception $e) { $serv->shutdown(); } catch (Throwable $throwable) { $serv->shutdown(); }客戶端發送請求"SW", "token" => "Bb1R3YLipbkTp5p0", "param" => [ "class" => "Order", "method" => "add", "param" => [ "code" => "C".mt_rand(1000,9999), "name" => "訂單-".mt_rand(1000,9999), ], ], ]; //編輯 $demo = [ "type" => "SW", "token" => "Bb1R3YLipbkTp5p0", "param" => [ "class" => "Order", "method" => "edit", "param" => [ "id" => "4", "name" => "訂單-".mt_rand(1000,9999), ], ], ]; //刪除 $demo = [ "type" => "SW", "token" => "Bb1R3YLipbkTp5p0", "param" => [ "class" => "Order", "method" => "del", "param" => [ "id" => "1", ], ], ]; //查詢 $demo = [ "type" => "SW", "token" => "Bb1R3YLipbkTp5p0", "param" => [ "class" => "Order", "method" => "info", "param" => [ "code" => "C4649" ], ], ]; $ch = curl_init(); $options = [ CURLOPT_URL => "http://10.211.55.4:9509/", CURLOPT_POST => 1, CURLOPT_POSTFIELDS => json_encode($demo), ]; curl_setopt_array($ch, $options); curl_exec($ch); curl_close($ch);擴展官方協程 MySQL 客戶端手冊:
https://wiki.swoole.com/wiki/...
大家可以嘗試使用官方提供的其他方法。
小結Demo 代碼僅供參考,里面有很多不嚴謹的地方。
根據自己的需要進行修改,比如業務代碼相關驗證,CURD 方法封裝 ...
推薦一個完善的產品,Swoole 開發的 MySQL 數據庫連接池(SMProxy):
https://github.com/louislivi/...
上面的 Demo 需要源碼的,加我微信。(菜單-> 加我微信-> 掃我)
推薦閱讀系統的講解 - SSO 單點登錄
系統的講解 - PHP WEB 安全防御
系統的講解 - PHP 緩存技術
系統的講解 - PHP 接口簽名驗證
系統的講解 - PHP 浮點數高精度運算
本文歡迎轉發,轉發請注明作者和出處,謝謝!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/31577.html
摘要:基于擴展實現真正的數據庫連接池這種方案中,項目占用的連接數僅僅為。一種是連接暫時不再使用,其占用狀態解除,可以從使用者手中交回到空閑隊列中這種我們稱為連接的歸隊。源碼剖析系列目錄 作者:bromine鏈接:https://www.jianshu.com/p/1a7...來源:簡書著作權歸作者所有,本文已獲得作者授權轉載,并對原文進行了重新的排版。Swoft Github: https:...
摘要:一個基于協議,開發的數據庫連接池。也可以通過其自身的管理機制來監視數據庫連接的數量使用情況等。超出最大連接數會采用協程掛起,等到有連接關閉再恢復協程繼續操作。 SMProxy GITHUB:https://github.com/louislivi/... Swoole MySQL Proxy 一個基于 MySQL 協議,Swoole 開發的MySQL數據庫連接池。 原理 將數據庫連接作...
閱讀 3388·2022-01-04 14:20
閱讀 3117·2021-09-22 15:08
閱讀 2203·2021-09-03 10:44
閱讀 2321·2019-08-30 15:44
閱讀 1500·2019-08-29 18:40
閱讀 2665·2019-08-29 17:09
閱讀 2993·2019-08-26 13:53
閱讀 3226·2019-08-26 13:37