通用連線池幫你解決資源管理難題

kevwan發表於2021-05-25

前言

群里老有同學問,go-zero資料庫redis 庫是否有連線池支援。先說結論:有的,可以放心大膽用!

從框架設計來說,對於資料庫連線這種資源當然是儘可能減少頻繁操作:

  1. 為業務減負
  2. 提升框架自身的效能
  3. 池化技術是一個通用化技術,本身就應該作為一個通用庫支撐框架的上層業務

所以不管是 sqlxredis,以及 mongo,等以後可能要支援的資料來源型別,底層的池化處理都是通用的;所以當開發者需要一個池化處理元件時,go-zero 也是提供的。

池化技術支援的庫就位於:core/resourcemanager.go。下面來看看這個庫的使用~~

使用

使用的話,我們直接來看 sqlx ,它是怎麼用的:

// 1. 初始化
var connManager = syncx.NewResourceManager()

func getCachedSqlConn(driverName, server string) (*db, error) {
  val, err := connManager.GetResource(server, func() (io.Closer, error) {
    // 2. 此處才是真正建立連線的地方
    conn, err := newDBConnection(driverName, server)
    ...
    // 3. 將連線返回給連線池【內部也肯定是存起來】
    return &db{
      DB: conn,
    }, nil
  })
  ...
  return val.(*db), nil
}

說說其中的要點:

  1. NewResourceManager:建立一個池子
  2. GetResource(key, createFunc):key是用來防止併發獲取資源時重複請求,createFunc 才是正在用來建立資源的函式【此函式需要有開發者自己編寫符合業務需求資源】

總結一下資源池的模型:

// 1. new
var manager = NewResourceManager()

// 2. 業務資源獲取函式
func getResource(key string) (*resource, error) {
  return manager.GetResource(key, createFunc);
}

// 3.業務資源建立函式【由開發者自己編寫,此處只是一個樣例】
func createFunc() (io.Closer, error) {
  // 開啟一個資源
  conn, err := openResource();
  // 設定一下資源配置
  conn.setConfig()

  return conn, err;
}

整體分析

其實流程上很簡單,其中還有我們老生常談的 sharedCalls

  1. GetResource,攜帶特定的 key,到資源池中的 map 中查詢:
    • 查到了,直接返回
    • 沒有查到,呼叫傳入的 create() ;此處才真正建立一個真實的資源連線,並放入 map
  2. 其中對 map 的查詢和寫入,都得加鎖。
  3. 其中在對資源池進行操作時,附加上 sharedCalls :防止併發請求時無效流量請求以及共享請求結果。

關於 SharedCalls,還不清楚的同學,可以到 go-zero 官方文件中仔細檢視。

總結

本篇文章對 go-zero 的資源池庫從使用到結構進行了分析。大家也可以在業務中常發生資源申請的邏輯處,加上 resourcemanager,本質上也是給資源加上一個快取,節省反覆建立。

關於 go-zero 更多的設計和實現文章,可以關注『微服務實踐』公眾號。

專案地址

github.com/tal-tech/go-zero

歡迎使用 go-zero 並 star 支援我們!

微信交流群

關注『微服務實踐』公眾號並點選 交流群 獲取社群群二維碼。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章