中文 | English
<https://yq.aliyun.com/go/articleRenderRedirect?url=.%2FREADME-EN.md>
SMProxy
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fgithub.com%2Flouislivi%2Fsmproxy>
喜歡請star
github
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fgithub.com%2Flouislivi%2Fsmproxy>
:https://github.com/louislivi/smproxy
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fgithub.com%2Flouislivi%2Fsmproxy>
Swoole MySQL Proxy
一個(gè)基于 MySQL 協(xié)議,Swoole 開發(fā)的MySQL數(shù)據(jù)庫連接池。
原理
將數(shù)據(jù)庫連接作為對象存儲在內(nèi)存中,當(dāng)用戶需要訪問數(shù)據(jù)庫時(shí),首次會建立連接,后面并非建立一個(gè)新的連接,而是從連接池中取出一個(gè)已建立的空閑連接對象。
使用完畢后,用戶也并非將連接關(guān)閉,而是將連接放回連接池中,以供下一個(gè)請求訪問使用。而連接的建立、斷開都由連接池自身來管理。
同時(shí),還可以通過設(shè)置連接池的參數(shù)來控制連接池中的初始連接數(shù)、連接的上下限數(shù)以及每個(gè)連接的最大使用次數(shù)、最大空閑時(shí)間等等。
也可以通過其自身的管理機(jī)制來監(jiān)視數(shù)據(jù)庫連接的數(shù)量、使用情況等。超出最大連接數(shù)會采用協(xié)程掛起,等到有連接關(guān)閉再恢復(fù)協(xié)程繼續(xù)操作。
特性
* 支持讀寫分離
* 支持?jǐn)?shù)據(jù)庫連接池,能夠有效解決 PHP 帶來的數(shù)據(jù)庫連接瓶頸
* 支持 SQL92 標(biāo)準(zhǔn)
* 采用協(xié)程調(diào)度
* 支持多個(gè)數(shù)據(jù)庫連接,多個(gè)數(shù)據(jù)庫,多個(gè)用戶,靈活搭配
* 遵守 MySQL 原生協(xié)議,跨語言,跨平臺的通用中間件代理
* 支持 MySQL 事務(wù)
* 支持 HandshakeV10 協(xié)議版本
* 完美兼容 MySQL4.1 - 8.0
* 兼容各大框架,無縫提升性能
設(shè)計(jì)初衷
PHP 沒有連接池,所以高并發(fā)時(shí)數(shù)據(jù)庫會出現(xiàn)連接打滿的情況,Mycat 等數(shù)據(jù)庫中間件會出現(xiàn)部分 SQL 無法使用,例如不支持批量添加等,而且過于臃腫。
所以就自己編寫了這個(gè)僅支持連接池和讀寫分離的輕量級中間件,使用 Swoole 協(xié)程調(diào)度 HandshakeV10 協(xié)議轉(zhuǎn)發(fā)使程序更加穩(wěn)定,不用像 Mycat
一樣解析所有 SQL 包體,增加復(fù)雜度。
環(huán)境
* Swoole 2.1+
* PHP 7.0+
安裝
(推薦)直接下載最新發(fā)行版的 PHAR 文件,解壓即用:
https://github.com/louislivi/smproxy/releases/latest
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fgithub.com%2Flouislivi%2Fsmproxy%2Freleases%2Flatest>
或者使用 Git 切換任意版本:
git clone https://github.com/louislivi/smproxy.git composer install --no-dev #
如果你想貢獻(xiàn)你的代碼,請不要使用 --no-dev 參數(shù)。
運(yùn)行
需要給予 bin/SMProxy 執(zhí)行權(quán)限。
SMProxy [ start | stop | restart | status | reload ] [ -c | --config
<configuration_path> ] SMProxy -h | --help SMProxy -v | --version
Options:
* start 運(yùn)行服務(wù)
* stop 停止服務(wù)
* restart 重啟服務(wù)
* status 查詢服務(wù)運(yùn)行狀態(tài)
* reload 平滑重啟
* -h --help 幫助
* -v --version 查看當(dāng)前服務(wù)版本
* -c --config 設(shè)置配置項(xiàng)目錄
SMProxy連接測試
測試SMProxy與測試MySQL完全一致,MySQL怎么連接,SMProxy就怎么連接。
推薦先采用命令行測試:
(請勿使用MYSQL8.0客戶端鏈接測試)
mysql -uroot -p123456 -P3366 -h127.0.0.1
也可采用工具連接。
沒用框架的 PHP 7.2.6
沒用:0.15148401260376,用了:0.040808916091919
未使用連接池: 0.15148401260376
使用連接池: 0.040808916091919
ThinkPHP 5.0
未使用連接池:
使用連接池:
Laravel 5.7
未使用連接池:
使用連接池:
MySQL 連接數(shù)
未使用連接池:
使用連接池:
請以實(shí)際壓測為準(zhǔn),根數(shù)據(jù)量,網(wǎng)絡(luò)環(huán)境,數(shù)據(jù)庫配置有關(guān)。
測試中因超出最大連接數(shù)會采用協(xié)程掛起 等到有連接關(guān)閉再恢復(fù)協(xié)程繼續(xù)操作,
所有并發(fā)量與配置文件maxConns設(shè)置的不合適,會導(dǎo)致比原鏈接慢,主要是為了控制連接數(shù)。
交流
QQ群:722124111
配置文件
* 配置文件位于 smproxy/conf 目錄中,其中大寫 ROOT 代表當(dāng)前 SMProxy 根目錄。
database.json
{ "database": { "account": { "自定義用戶名": { "user": "必選,數(shù)據(jù)庫賬戶", "password":
"必選,數(shù)據(jù)庫密碼" }, "...": "必選1個(gè),自定義用戶名 與serverInfo中的account相對應(yīng)" }, "serverInfo": {
"自定義數(shù)據(jù)庫連接信息": { "write": { "host": "必選,寫庫地址 多個(gè)用[]表示", "port": "必選,寫庫端口",
"timeout": "必選,寫庫連接超時(shí)時(shí)間(秒)", "account": "必選,自定義用戶名 與 account中的自定義用戶名相對應(yīng)" },
"read": { "host": "可選,讀庫地址 多個(gè)用[]表示", "port": "可選,讀庫端口", "timeout":
"可選,讀庫連接超時(shí)時(shí)間(秒)", "account": "可選,自定義用戶名 與 account中的自定義用戶名相對應(yīng)" } }, "...":
"必選1個(gè),自定義數(shù)據(jù)庫連接信息 與databases中的serverInfo相對應(yīng),read讀庫可不配置" }, "databases": {
"數(shù)據(jù)庫名稱": { "serverInfo": "必選,自定義數(shù)據(jù)庫連接信息 與serverInfo中的自定義數(shù)據(jù)庫連接信息相對應(yīng)",
"maxConns": "必選,該庫服務(wù)最大連接數(shù),支持計(jì)算", "maxSpareConns": "必選,該庫服務(wù)最大空閑連接數(shù),支持計(jì)算",
"startConns": "可選,該庫服務(wù)默認(rèn)啟動(dòng)連接數(shù),支持計(jì)算", "maxSpareExp":
"可選,該庫服務(wù)空閑連接數(shù)最大空閑時(shí)間(秒),默認(rèn)為0,支持計(jì)算", "charset": "可選,該庫編碼格式" }, "...": "必選1個(gè),數(shù)據(jù)庫名稱
多個(gè)數(shù)據(jù)庫配置多個(gè)" } } }
*
maxConns,maxSpareConns,startConns
* 推薦設(shè)置為server.json中配置的worker_num的倍數(shù)swoole_cpu_num()*N
*
多個(gè)讀庫,寫庫
* 目前采取的是隨機(jī)獲取連接,推薦將maxConns,startConns,startConns至少設(shè)置為max(讀庫,寫庫)*worker_num
的1倍以上
server.json
{ "server": { "user": "必選,SMProxy服務(wù)用戶", "password": "必選,SMProxy服務(wù)密碼",
"charset": "可選,SMProxy編碼,默認(rèn)utf8mb4", "host": "可選,SMProxy地址,默認(rèn)0.0.0.0", "port":
"可選,SMProxy端口,默認(rèn)3366 如需多個(gè)以`,`隔開", "mode":
"可選,SMProxy運(yùn)行模式,SWOOLE_PROCESS多進(jìn)程模式(默認(rèn)),SWOOLE_BASE基本模式", "sock_type":
"可選,sock類型,SWOOLE_SOCK_TCP tcp", "logs": { "open":"必選,日志開關(guān),true 開 false 關(guān)",
"config": { "system": { "log_path": "必選,SMProxy系統(tǒng)日志目錄", "log_file":
"必選,SMProxy系統(tǒng)日志文件名", "format": "必選,SMProxy系統(tǒng)日志目錄日期格式" }, "mysql": { "log_path":
"必選,SMProxyMySQL日志目錄", "log_file": "必選,SMProxyMySQL日志文件名", "format":
"必選,SMProxyMySQL日志目錄日期格式" } } }, "swoole": { "worker_num": "必選,SWOOLE
worker進(jìn)程數(shù),支持計(jì)算", "max_coro_num": "必選,SWOOLE 協(xié)程數(shù),推薦不低于3000", "pid_file":
"必選,worker進(jìn)程和manager進(jìn)程pid目錄", "open_tcp_nodelay": "可選,關(guān)閉Nagle合并算法",
"daemonize": "可選,守護(hù)進(jìn)程化,true 為守護(hù)進(jìn)程 false 關(guān)閉守護(hù)進(jìn)程", "heartbeat_check_interval":
"可選,心跳檢測", "heartbeat_idle_time": "可選,心跳檢測最大空閑時(shí)間", "reload_async":
"可選,異步重啟,true 開啟異步重啟 false 關(guān)閉異步重啟", "log_file": "可選,SWOOLE日志目錄" },
"swoole_client_setting": { "package_max_length": "可選,SWOOLE Client
最大包長,默認(rèn)16777216MySQL最大支持包長" }, "swoole_client_sock_setting": { "sock_type":
"可選,SWOOLE Client sock 類型,默認(rèn)tcp 僅支持tcp" } } }
*
user,password,port,host
* 為SMProxy的賬戶|密碼|端口|地址(非Mysql數(shù)據(jù)庫賬戶|密碼|端口|地址)
* 可隨意設(shè)置用于SMProxy登錄驗(yàn)證
* 例如默認(rèn)配置登錄為mysql -uroot -p123456 -P 3366 -h 127.0.0.1
* SMProxy登錄成功MySQL COMMIT會提示Server version: 5.6.0-SMProxy
*
worker_num
* 推薦使用swoole_cpu_num() 或 swoole_cpu_num()*N
MySQL8.0
* SMProxy1.2.4及以上可直接使用
* SMProxy1.2.4以下需要做兼容處理
MySQL-8.0默認(rèn)使用了安全性更強(qiáng)的caching_sha2_password插件,其他版本如果是從5.x升級上來的, 可以直接使用所有MySQL功能,
如是新建的MySQL, 需要進(jìn)入MySQL命令行執(zhí)行以下操作來兼容: ALTER USER 'root'@'%' IDENTIFIED WITH
mysql_native_password BY 'password'; flush privileges;
將語句中的 'root'@'%' 替換成你所使用的用戶, password 替換成其密碼.
如仍無法使用, 應(yīng)在my.cnf中設(shè)置 default_authentication_plugin = mysql_native_password
其他學(xué)習(xí)資料
* MySQL協(xié)議分析 :https://www.cnblogs.com/davygeek/p/5647175.html
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.cnblogs.com%2Fdavygeek%2Fp%2F5647175.html>
* MySQL官方協(xié)議文檔 :
https://dev.MySQL.com/doc/internals/en/connection-phase-packets.html#packet-Protocol::Handshake
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fdev.MySQL.com%2Fdoc%2Finternals%2Fen%2Fconnection-phase-packets.html%23packet-Protocol%3A%3AHandshake>
* Mycat源碼 :https://github.com/MyCATApache/Mycat-Server
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fgithub.com%2FMyCATApache%2FMycat-Server>
* Swoole :https://www.swoole.com/
<https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fwww.swoole.com%2F>
熱門工具 換一換