gpt4 book ai didi

go - 在 Go 中管理每个请求的连接

转载 作者:IT王子 更新时间:2023-10-29 02:22:19 26 4
gpt4 key购买 nike

假设地说,为每个请求连接到数据库并在请求完成时关闭是否是一种好的做法?

我在数据库中使用 mongodbmgo

在我的项目中,我想通过从请求头中获取数据库名称来连接到某个数据库(当然,这与身份验证机制相结合,例如我的应用程序中的 JWT)。流程是这样的:

  1. 用户认证:

    POST to http://api.app.com/authenticate
    // which checks the user in a "global" database,
    // authenticates them and returns a signed JWT token
    // The token is stored in bolt.db for the authentication mechanism
  2. 一些 RESTful 操作

    POST to http://api.app.com/v1/blog/posts
    // JWT middleware for each request to /v1* is set up
    // `Client-Domain` in header is set to a database's name, e.g 'app-com'
    // so we open a connection to that database and close when
    // request finishes

所以我的问题是:

  1. 这可行吗? - 我已经阅读了有关连接池和重用它们的内容,但我还没有阅读太多关于它们的内容
  2. 是否有更好的方法来实现所需的功能?
  3. 如何确保 session 仅在请求完成时关闭?

我需要这样做的原因是因为我们有多个 vendor ,他们拥有相同的数据库集合,但具有不同的条目,并且对他们自己的数据库的访问受到限制。

更新/解决方案我最终使用了 Go 的内置 Context,方法是复制 session 并在需要执行任何 CRUD 操作的任何地方使用它

类似于:

func main() {
...
// Configure connection and set in global var
model.DBSession, err = mgo.DialWithInfo(mongoDBDialInfo)
defer model.DBSession.Close()
...

n := negroni.Classic()
n.Use(negroni.HandlerFunc(Middleware))

...
}

func Middleware(res http.ResponseWriter, req *http.Request, next http.HandlerFunc) {

...
db := NewDataStore(clientDomain)
// db.Close() is an alias for ds.session.Close(), code for this function is not included in this post
// Im still experimenting with this, I need to make sure the session is only closed after a request has completed, currently it does not always do so
defer db.Close()

ctx := req.Context()
ctx = context.WithValue(ctx, auth.DataStore, db)
req = req.WithContext(ctx)
...
}

func NewDataStore(db string) *DataStore {
store := &DataStore{
db: DBSession.Copy().DB(db),
session: DBSession.Copy(),
}
return store
}

然后在 HandlerFunc 中使用它,例如 /v1/system/users:

func getUsers(res http.ResponseWriter, req *http.Request) {
db := req.Context().Value(auth.DataStore).(*model.DataStore)
users := make([]SystemUser{}, 0)
// db.C() is an alias for ds.db.C(), code for this function is not included in this post
db.C("system_users").Find(nil).All(&users)
}

与我试验的原始方法相比,响应时间减少了 40%。

最佳答案

假设地说不是一个好的做法,因为:

  1. 数据库逻辑分散在几个包中。
  2. 很难测试
  3. 不能应用DI(主要是代码很难维护)

回复您的问题:

  1. 是可行的,但您不会使用它们 go 包中的连接池(如果您想了解有关连接池的更多信息,请查看代码 here)
  2. 更好的方法是创建一个包含数据库连接的全局变量,并在应用程序将要停止时关闭(而不是每次请求都关闭连接)
  3. 我如何确保 session 仅在请求完成时关闭<- 您应该检查数据库查询的答案,然后关闭连接(但我不建议在请求后关闭连接,因为您将需要为另一个请求再次打开并再次关闭等...)

关于go - 在 Go 中管理每个请求的连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42222797/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com