【问题标题】:Concurrency in gopkg.in/mgo.v2 (Mongo, Go)gopkg.in/mgo.v2 中的并发(Mongo,Go)
【发布时间】:2017-02-27 17:25:25
【问题描述】:

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

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

或者我应该打电话给Session.CopySession.Close -> 建立会话池。

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

【问题讨论】:

    标签: mongodb go mgo


    【解决方案1】:

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

    所有 Session 方法都是并发安全的,可以从多个 goroutine 中调用。

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

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

    另见Sessions的使用相关问题:mgo - query performance seems consistently slow (500-650ms)

    【讨论】:

      【解决方案2】:

      调用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
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-11-16
        • 2015-12-24
        • 2023-03-27
        • 1970-01-01
        • 2019-03-25
        • 2019-05-09
        • 1970-01-01
        • 2012-01-04
        • 1970-01-01
        相关资源
        最近更新 更多