gopkg.in/mgo.v2 (Mongo, Go) 中的并发

Concurrency in gopkg.in/mgo.v2 (Mongo, Go)

我想在用 Go 编写的 webapp 中使用 MongoDB。

我可以拥有一个 mgo.Session 并在网络应用程序中同时使用它吗?例如在 http.Handler

或者我应该调用 Session.CopySession.Close -> 创建会话池。

这听起来很矛盾,我读到池已经在 mgo.Session 内部实现,我可以同时使用会话,而在其他地方我读到我需要 CopyClose

调用DialDialWithTimeoutDialWithInfo将建立连接池。如果您需要多个会话,则需要调用 session.Copy() 或 session.New(),首选 session.Copy(),因为它将保留授权。这是一个例子:

假设您有一个 UserService 结构来处理您所有的用户数据库需求。请注意,这是我的想法,因此可能存在一些语法错误,但想法就在那里。

type Userservice struct {
    DB *mgo.Session
}

func (s *Userservice) Create(u *User) error {
    sessionCopy := s.DB.Copy()
    defer sessionCopy.Close()

    db := sessionCopy.DB("test_db")
    col := db.C("users")

    if err := col.Insert(u); err != nil {
        return err
    }
}

mgo.Session 可以安全地同时使用。引用其文档:

All Session methods are concurrency-safe and may be called from multiple goroutines.

但这并不意味着您不应该通过调用 Session.Copy() or Session.Clone() 在拨号时获得的初始会话中并行创建和使用它们。

并发安全和从使用更多并发中获益并不相互排斥(它们不是互斥)。虽然您可以使用来自任意数量的 goroutine 的单个 mgo.Session,但这不会很好地扩展,根本不会扩展 。会话自动管理一个连接池,甚至可能连接到多个服务器节点,但如果您使用单个 Session,您就没有利用它。通过在每个请求的开头创建一个新的 Session(如果需要),并在结尾正确关闭它(使用 Session.Close();最好使用 defer 调用),您正在潜在地同时使用多个连接的优势,可能到多个服务器节点(如果可用),从而更好地利用服务器资源;并获得更快的响应时间(从数据库到最终到您的 HTTP 最终用户)。调用 Session.Close() 不会关闭与服务器的底层连接,它只会将连接放回池中,准备好被另一个会话拾取。

另请参阅有关使用 Sessions 的相关问题: