原文地址:https://blog.fanscore.cn/a/53/
本文是與世界分享我剛編的轉發ntunnel_mysql.php的工具的後續,之前的實現有些拉胯,這次重構了下。需求背景是為了在本地macbook上通過開源的mysql視覺化使用者端(dbeaver、Sequel Ace等)存取我司測試環境的mysql,整個測試環境的如圖所示:
那麼就有以下幾種方式:
既然上面的方式都不行,那怎麼辦呢?因此我產生了一個大膽的想法
大概架構如下
首先,在本地pc上啟動一個sidecar
程序,該程序監聽3306
埠,實現mysql協定,將自己偽裝為一個mysql server。本地pc上的mysql使用者端連線到sidecar
,傳送請求封包給sidecar
,從sidecar
讀取響應包。
然後在測試環境某臺機器上啟動transport
程序,該程序啟動http服務,由nginx代理轉發請求,相當於監聽在80埠,然後連線到測試環境的mysql server。
sidecar
會將來自使用者端的請求包通過http請求轉發給transport
,transport
將請求包轉發到測試環境對應的mysql server,然後讀取mysql的響應封包,然後將響應封包返回給sidecar
,sidecar
再將響應包返回給mysql使用者端。
遵循上述的基本原理,我將其實現出來: https://github.com/Orlion/hersql。但是在描述hersql
的實現細節之前我們有必要了解下mysql協定
mysql使用者端與伺服器端互動過程主要分為兩個階段:握手階段與命令階段。互動流程如下:
在最新版本中,握手過程比上面要複雜,會多幾次互動
在握手階段,3次握手建立tcp連線後伺服器端會首先傳送一個握手初始化包,包含了
隨後使用者端會傳送一個登入認證包,包含了:
伺服器端收到使用者端發來的登入認證包驗證通過後會傳送一個OK包,告知使用者端連線成功,可以轉入命令互動階段
在mysql 8.0預設的身份驗證外掛為
caching_sha2_password
,低版本為mysql_native_password
,兩者的驗證互動流程有所不同個,caching_sha2_password
在快取未命中的情況下還會多幾次互動。另外如果伺服器端與使用者端的驗證外掛不同的話,也是會多幾次互動。
在命令階段,使用者端會傳送命令請求包到伺服器端。封包的第一個位元組標識了當前請求的型別,常見的命令有:
請求響應的模式是使用者端會發一個請求包,伺服器端會回覆n(n>=0)
個響應包
最後使用者端斷開連線時會主動傳送一個COM_QUIT
命令包通知伺服器端斷開連線
在瞭解mysql協定之後我們就可以來看下hersql的資料流轉過程了。
上面介紹了一堆原理性的東西,那麼如何使用呢?
首先你需要下載下來hersql
的原始碼:https://github.com/Orlion/hersql,還需要安裝下golang
,這些都完成後你就可以啟動hersql transport
了。但是先彆著急,我先解釋下transport
的組態檔tranport.example.yaml
:
server:
# transport http服務監聽的地址
addr: :8080
log:
# 標準輸出的紀錄檔的紀錄檔級別
stdout_level: debug
# 檔案紀錄檔的紀錄檔級別
level: error
# 檔案紀錄檔的檔案地址
filename: ./storage/transport.log
# 紀錄檔檔案的最大大小(以MB為單位), 預設為 100MB。紀錄檔檔案超過此大小會建立個新檔案繼續寫入
maxsize: 100
# maxage 是根據檔名中編碼的時間戳保留舊紀錄檔檔案的最大天數。
maxage: 168
# maxbackups 是要保留的舊紀錄檔檔案的最大數量。預設是保留所有舊紀錄檔檔案。
maxbackups: 3
# 是否應使用 gzip 壓縮旋轉的紀錄檔檔案。預設是不執行壓縮。
compress: false
你可以根據你的需求修改設定,然後就可以啟動transport
了
$ go run cmd/transport/main.go -conf=transport.example.yaml
一般情況下都是會先編譯為可執行檔案,由systemd之類的工具託管transport程序,保證transport存活。這裡簡單期間直接用go run起來
同樣的,你需要下載下來hersql
的原始碼:https://github.com/Orlion/hersql,提前安裝好golang
。修改下sidecar
的組態檔sidecar.example.yaml
:
server:
# sidecar 監聽的地址,之後mysql client會連線這個地址
addr: 127.0.0.1:3306
# transport http server的地址
transport_addr: http://x.x.x.x:xxxx
log:
# 與transport設定相同
就可以啟動sidecar
了
$ go run cmd/sidecar/main.go -conf=sidecar.example.yaml
同樣的,一般情況下也都是會先編譯為可執行檔案,mac上是launchctl之類的工具託管sidecar程序,保證sidecar存活。這裡簡單期間直接用go run起來
上面的步驟都執行完成後,就可以開啟mysql使用者端使用了。資料庫地址和埠號需要填寫sidecar
組態檔中的addr
地址,sidercar
不會校驗使用者名稱和密碼,因此使用者名稱密碼可以隨意填寫
重點來了: 資料庫名必須要填寫,且必須要按照以下格式填寫
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
舉個例子:
root:123456@tcp(10.10.123.123:3306)/BlogDB
如圖所示:
目標mysql伺服器
可以直連目標mysql伺服器的機器
那麼transport
可以設定為
server:
addr: :8080
sidecar
可以設定為
server:
addr: 127.0.0.1:3306
transport_addr: http://10.10.123.100:8080
使用者端連線設定
root:123456@tcp(10.10.123.123:3306)/BlogDB
如果hersql對你有幫助歡迎點個star