亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

aws-lambda 上的 sql.DB 連接太多

aws-lambda 上的 sql.DB 連接太多

Go
吃雞游戲 2023-06-01 14:14:37
正如我在 Golang 中的理解:the DB handle is meant to be long-lived and shared between many goroutines.但是當我將 Golang 與 AWS lambda 結合使用時,情況就完全不同了,因為 lambda 會在函數完成時停止該函數。我正在使用:defer db.Close()在 Lambda Invoke 函數中,但它沒有影響。在 MySQL 上,它仍將連接保持為Sleep query. 結果,它導致too many connections了 MySQL。目前,我必須wait_timeout在 MySQL 中設置為小數。但在我看來,這不是最好的解決方案。在 Lambda 中使用 Go SQL 驅動程序時,有什么方法可以關閉連接嗎?謝謝,
查看完整描述

1 回答

?
慕標5832272

TA貢獻1966條經驗 獲得超4個贊

我們需要解決兩個問題

  • 正確管理 lambda 調用之間的狀態

  • 配置連接池

正確管理狀態

讓我們稍微了解一下 AWS 是如何管理容器的。來自AWS 文檔:

執行 Lambda 函數后,AWS Lambda 會在一段時間內維護執行上下文,以等待另一個 Lambda 函數調用。實際上,如果 AWS Lambda 選擇在再次調用 Lambda 函數時重用上下文,服務會在 Lambda 函數完成后凍結執行上下文,并解凍上下文以供重用。這種執行上下文重用方法具有以下含義:

  • Lambda 函數代碼中的任何聲明(在處理程序代碼之外,請參閱編程模型)保持初始化狀態,從而在再次調用該函數時提供額外的優化。例如,如果您的 Lambda 函數建立數據庫連接,而不是重新建立連接,則在后續調用中使用原始連接。我們建議在您的代碼中添加邏輯以在創建連接之前檢查連接是否存在。

  • 每個執行上下文在 /tmp 目錄中提供 500MB 的額外磁盤空間。當執行上下文被凍結時,目錄內容仍然存在,提供可用于多次調用的臨時緩存。您可以添加額外的代碼來檢查緩存是否包含您存儲的數據。有關部署限制的信息,請參閱 AWS Lambda 限制。

  • 如果 AWS Lambda 選擇重用執行上下文,則由您的 Lambda 函數啟動但在函數結束時未完成的后臺進程或回調將恢復。您應該確保代碼中的任何后臺進程或回調(在 Node.js 的情況下)在代碼退出之前完成。

第一個要點表示狀態在執行之間保持不變。讓我們看看實際效果:

let?counter?=?0
module.exports.handler?=?(event,?context,?callback)?=>?{
??counter++
??callback(null,?{?count:?counter?})
}

如果您部署它并連續多次調用,您將看到計數器將在兩次調用之間遞增。

現在您知道了 - 您不應該調用defer db.Close(),而應該重用數據庫實例。您可以通過簡單地創建db一個包級變量來做到這一點。

首先,創建一個將導出Open函數的數據庫包:

package database


import (

? ? "fmt"

? ? "os"


? ? _ "github.com/go-sql-driver/mysql"

? ? "github.com/jinzhu/gorm"

)


var (

? ? host = os.Getenv("DB_HOST")

? ? port = os.Getenv("DB_PORT")

? ? user = os.Getenv("DB_USER")

? ? name = os.Getenv("DB_NAME")

? ? pass = os.Getenv("DB_PASS")

)


func Open() (db *gorm.DB) {

? ? args := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, pass, host, port, name)

? ? // Initialize a new db connection.

? ? db, err := gorm.Open("mysql", args)

? ? if err != nil {

? ? ? ? panic(err)

? ? }

? ? return

}

然后在你的 handler.go 文件中使用它:


package main


import (

? ? "context"


? ? "github.com/aws/aws-lambda-go/events"

? ? "github.com/aws/aws-lambda-go/lambda"

? ? "github.com/jinzhu/gorm"

? ? "github.com/<username>/<name-of-lib>/database"

)


var db *gorm.DB


func init() {

? ? db = database.Open()

}


func Handler() (events.APIGatewayProxyResponse, error) {

? ? // You can use db here.

? ? return events.APIGatewayProxyResponse{

? ? ? ? StatusCode: 201,

? ? }, nil

}


func main() {

? ? lambda.Start(Handler)

}

OBS:不要忘記替換github.com/<username>/<name-of-lib>/database為正確的路徑。

現在,您可能仍然會看到too many connections錯誤。如果發生這種情況,您將需要一個連接池。

配置連接池

在軟件工程中,連接池是維護的數據庫連接的緩存,以便在以后需要對數據庫的請求時可以重用這些連接。連接池用于增強在數據庫上執行命令的性能。

您將需要一個連接池,允許的連接數必須等于運行的并行 lambda 數,您有兩種選擇:

  • MySQL 代理

MySQL Proxy 是一個簡單的程序,位于您的客戶端和 MySQL 服務器之間,可以監視、分析或轉換它們的通信。它的靈活性允許廣泛的用途,包括負載平衡、故障轉移、查詢分析、查詢過濾和修改等等。

  • AWS 極光:

Amazon Aurora Serverless 是 Amazon Aurora(MySQL 兼容版本)的按需自動擴展配置,其中數據庫將根據您的應用程序的需要自動啟動、關閉和擴展或縮減容量。它使您能夠在云中運行數據庫而無需管理任何數據庫實例。對于不頻繁、間歇性或不可預測的工作負載,這是一種簡單、經濟高效的選擇。

無論您選擇哪種方式,互聯網上都有大量關于如何配置兩者的教程。


查看完整回答
反對 回復 2023-06-01
  • 1 回答
  • 0 關注
  • 176 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號