如何介入 Connection Pool?
參考連結
- Hikari Connection Pooling with Spring Boot
- AWS RDS Proxy
- Hikrai-Source Code
- AWS推出能提升關聯式資料庫應用可擴展性的代理服務
- Hikrari配置設定
- 注入是用於監控的Druid dataSource
- 如何指定自己extends Hirkari的DataSource
- 如何构建实用的RDS Proxy? (一):有稍微提到怎麼使用Golang實作一個RDS Proxy
- kingshard:一個開源的Mysql Proxy但是已經沒在維護了,是用GO寫的
- MySQL官网连接过程介绍:官方連線協議說明
- mysql握手协议抓包: 有大概說明mysql的協議抓包內容
- 30-25之資料庫層的擴展 - 讀寫分離架構:資料庫的讀寫分離說明
前言
可以參考我的論文方向,是如何在資料庫中滿足零信任要求,零信任機制其實核心說白了就是存取控制機制,在Authentication驗證這個人是誰之時,取得所有相關的上下文,甚至是風險,經過多方考量後,最後做Authorization授權。那既然我們的目的在於,如何在資料庫中滿足零信任要求…
就要去探討到,做驗證和授權的地方在資料庫的哪裡?非Connection莫屬了。
但是到底有哪些方式可以介入Connection呢?
-
透過第三方介入connection Pool
- 講到驗證和授權,就會想到建立連線時,我們通常會提供driver, username, password, url來建立連線,而建立連線時最常提到的是Connection Pool,其實說白了就是一個application和datasource建立連線時的中間層,這個中間層可以做很多事情,像是連線池、讀寫分離、快取查詢結果等等。而我們就是要在這個中間層做驗證和授權。
- 簡單介入Connection Pool的方式,像可以改寫一些應用程式的第三方套件,像是Spring Boot使用的HikariDataSource
-
使用Database Proxy
- 我第一次看到這個詞是在看Hikari的Source Code時,發現有Proxy的連線設定。後來上網一查,立馬跳出來的就是AWS RDS Proxy。AWS RDS Proxy全名稱Relation Database。
- 透過Database Proxy也可以做到驗證和授權,簡單來說他就是介於多個應用程式跟資料庫的中間層。
- 與Connection Pool類似都是作為應用程式中間層的存在,但是應用面比較廣,因為他不是只有針對單一應用程式,而是作為所有應用程式的連線資料庫的入口。
使用Database Proxy
AWS RDS Proxy
AWS RDS Proxy是一個中間層的服務,可以讓應用程式與資料庫之間的連線更加穩定,並且提供了一些功能,像是連線池、讀寫分離、快取查詢結果等等。AWS有許多應用程式,像是AWS Lambda、Fargate、Amazon ECS或EKS,等多個應用程式中會有大量且快速地開啟或關閉,與資料庫伺服器間的連結的需求,而這樣的操作容易耗盡資料庫的記憶體和運算資源。
連接池:減輕建立新連接時,對資料庫記憶體和運算資源造成的影響
因此才有了RDS Proxy,Amazon RDS Proxy的執行個體會維護與RDS資料庫執行個體間建立的連接池,減輕建立新連接時,對資料庫記憶體和運算資源造成的影響,並且在應用程式間共用這些連結,進而提高資料庫的效率以及應用程式的可擴展性。
連線中斷:避免因為資料庫服務中斷,造成應用程式可用性問題
而且RDS Proxy能夠在維持現有連接的狀態下,連接新的資料庫執行個體,因此可以最大程度減少因為資料庫服務中斷,所造成的應用程式可用性問題,當資料庫故障時,RDS Proxy會直接將請求路由到新的資料庫執行個體,這樣可以使得故障轉移時間減少66%。
身份驗證:避免把權限寫死在程式碼中
RDS Proxy讓使用者可強制資料庫存取使用IAM身份驗證,因此將能避免資料庫憑證被寫死在程式碼中的安全性風險,多增加了一道的安全性控制,而且藉由RDS Proxy,使用者還能以AWS Secrets Manager集中管理資料庫憑證。
操作說明
其實做Database Proxy的好處就是,可以在不同應用程式中共享那個Connection來加快速度,在微服務的世界,不同應用存取一個database的需求很大,但是如果每個應用都要自己建立一個Connection,那麼就會造成資源的浪費,而且也不好管理。因此我們可以透過RDS Proxy來管理這些Connection,讓不同的應用程式共享同一個Connection。
可以參考以下影片了解Proxy怎麼建立和設定:
kingshard
kingshard是一個由Go開發高性能MySQL Proxy項目,可以做到以下幾點,也是可以作為零信任架構的可用功能:
- SQL的讀寫分離:讀寫分離最簡單的就是所有寫入的都寫入到一台服務,讀取時讀取一台服務。通常是主從式master-slave架構,由master負責寫的服務,會與 slave 進行資料同步。slave主要用來讀的服務。
- 透明的Connection Pool,不需要每次做連線: 透明的連線池,就是在應用程式中不需要額外的程式碼,就可以使用連線池的功能。
- SQL的日誌輸出:幾本上可以收集這些日誌,近一步做分析利用。
- SQL的黑白名單機制:支持客戶端IP訪問白名單機制,只有白名單中的IP才能訪問kingshard(支持IP 段)。甚至可以偵測SQL的內容,當偵測到有危險的SQL時,可以直接將該SQL拒絕執行。
架構說明
kingshard的整體工作流程如下所述:
- 讀取配置文件並啟動
- 在配置文件中設置的監聽端口監聽客戶端請求
- 收到客戶端連接請求後,啟動一個goroutine單獨處理該請求。
- 首選進行登錄驗證,驗證過程完全兼容MySQL認證協議,由於用戶名和密碼在配置文件中已經設置好,所以可以利用該信息驗證連接請求是否合法。
- 當用戶名和密碼都正確時,轉入下面的步驟,否則返回出錯信息給客戶端。
- 認證通過後,客戶端發送SQL語句。
- kingshard對客戶端發送過來的SQL語句,進行詞法和語義分析。識別出SQL的類型和生成SQL的路由計劃。如果有必要還會改寫SQL。然後轉發到相應的DB。
- 也有可能不做詞法和語義分析直接轉發到相應的後端DB。如果轉發SQL是分錶且跨多個DB,則每個DB對應啟動一個goroutine發送SQL和接收該DB返回的結果。
- 接收並合併結果,然後轉發給客戶端。
改寫 Hikari Datasource
除了Proxy之外,如果是針對特定應用程式,希望連線可以共享,而非每次建立新的Connection則可以考慮改寫Hikari Datasource。但是這個就不像Proxy那樣方便並且使用廣泛。就像前一篇Day09 - 淺入淺出 JDBC, Connection Pool所提到的,有很多第三方套件實作,其中spring boot預設採用Hikari,因為他是效能之冠。但是如果我們希望在getConnection()
的時候可以先驗證一下Application的身份,或是在prepareStatement()
的時候可以先驗證一下Application的權限,免不了要自己重新定義裡面的實作方法。
具體來說,可以怎麼重新撰寫自己的實作呢?
- 這個連結還算不錯:如何指定自己extends Hirkari的DataSource
繼承HikariDataSource
1 | public class MyHikariDataSource extends HikariDataSource { |
在config中設定自己的class
1 | spring.datasource.type=com.test.dao.MyHikariDataSource #指定自己的class |
我的下一步
目前比較能知道的是,透過Proxy能夠介入Connection Pool的應用面向更廣,所以接下來幾天要先能夠深入了解:
- [ ] 目前保護資料庫的方式與實施ZTA於Database的必要與
- [ ] 雲端不同proxy的功能比較,安全性的比較功能。
- [ ] 比較市面上目前有的solution,裡面缺了什麼樣的功能
- [ ] cloudfare zta tunnel 目的是建立安全的database connection, cloudfare 是讓遠端工作者可以安全連線
- [ ] 清楚你做出內容的貢獻可以是什麼?
在了解可以介入Connection Pool的方式後,決定要採用Proxy的方式進行研析,但是這就意味著要深入了解Mysql的連線協議,以及Proxy的實作方式。這個部分我會在下一篇文章中進行介紹。目前規劃如下:
- [ ] 深入了解Mysql協議
- [ ] 學習 Go 語言
- [ ] 深入了解Proxy的實作方式