ngu*_*890 4 connection-pooling go aws-lambda
据我在Golang中了解:the DB handle is meant to be long-lived and shared between many goroutines。
但是,当我将Golang与AWS lambda结合使用时,情况就大不相同了,因为lambda在完成后会停止该功能。
我正在使用:defer db.Close()在Lambda调用函数中,但不受影响。在MySQL上,该连接仍保持为Sleep query。结果,它too many connections在MySQL上引起。
目前,我必须wait_timeout在MySQL中设置较小的数量。但我认为这不是最佳解决方案。
在Lambda中使用Go SQL驱动程序时,有什么方法可以关闭连接?
谢谢,
我们需要解决两个问题
让我们了解一下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 })
}
Run Code Online (Sandbox Code Playgroud)
如果部署它并连续调用多次,您将看到计数器将在两次调用之间增加。
既然您知道了-您不应该调用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
}
Run Code Online (Sandbox Code Playgroud)
然后在您的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)
}
Run Code Online (Sandbox Code Playgroud)
OBS:别忘了github.com/<username>/<name-of-lib>/database用正确的路径替换。
现在,您可能仍然会看到too many connections错误。如果发生这种情况,您将需要一个连接池。
从维基百科:
在软件工程中,连接池是维护的数据库连接的缓存,以便在将来需要对数据库的请求时可以重新使用连接。连接池用于增强在数据库上执行命令的性能。
您将需要一个连接池,该连接池的允许连接数必须等于运行的并行lambda数,您有两种选择:
MySQL Proxy是一个简单的程序,位于您的客户端和MySQL服务器之间,可以监视,分析或转换其通信。它的灵活性允许广泛的用途,包括负载平衡,故障转移,查询分析,查询过滤和修改等等。
Amazon Aurora Serverless是针对Amazon Aurora(与MySQL兼容的版本)的按需自动扩展配置,该数据库将根据应用程序的需要自动启动,关闭和扩展或缩减容量。它使您可以在云中运行数据库,而无需管理任何数据库实例。对于不经常,间歇或不可预测的工作负载,这是一种简单,经济高效的选择。
无论您选择哪种方式,互联网上都有大量有关如何同时配置两者的教程。
| 归档时间: |
|
| 查看次数: |
1315 次 |
| 最近记录: |