为了账号安全,请及时绑定邮箱和手机立即绑定

维护 mgo 会话的最佳实践

维护 mgo 会话的最佳实践

Go
慕码人8056858 2021-08-23 17:49:20
我目前正在使用带有 mgo lib 的 mongodb 用于 Web 应用程序,但我不确定我使用它的方式是否好..package dbimport (    "gopkg.in/mgo.v2")const (    MongoServerAddr = "192.168.0.104"    RedisServerAddr = "192.168.0.104")var (    MongoSession, err = mgo.Dial(MongoServerAddr)    MDB  = MongoSession.DB("message")    MCol = MDB.C("new")    MSav = MDB.C("save")    UDB  = MongoSession.DB("account")    UCol = UDB.C("user"))我初始化 db 会话并创建接受集合和文档值的变量,因此当我需要查询集合时,我使用该变量来创建它。像那样:func UserExist(username string) bool {    user := Users{}    err := db.UCol.Find(bson.M{"username": username}).One(&user)    if err != nil {        return false    } else {        return true    }}那么有没有最佳实践或者这个很好..?谢谢
查看完整描述

3 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

我建议不要使用这样的全局会话。相反,您可以创建一个负责所有数据库交互的类型。例如:


type DataStore struct {

    session *mgo.Session

}


func (ds *DataStore) ucol() *mgo.Collection { ... }


func (ds *DataStore) UserExist(user string) bool { ... }

这种设计有很多好处。一个重要的是,它允许您同时进行多个会话,因此,例如,如果您有一个 http 处理程序,您可以创建一个本地会话,该会话由一个独立会话支持,仅用于该请求:


func (s *WebSite) dataStore() *DataStore {

    return &DataStore{s.session.Copy()}

}    


func (s *WebSite) HandleRequest(...) {

    ds := s.dataStore()

    defer ds.Close()

    ...

}

在这种情况下,mgo 驱动程序表现良好,因为会话在内部缓存和重用/维护。每个会话在使用时也将由一个独立的套接字支持,并且可以配置独立的设置,并且还将具有独立的错误处理。如果您使用单个全局会话,这些是您最终必须处理的问题。


查看完整回答
反对 回复 2021-08-23
?
倚天杖

TA贡献1828条经验 获得超3个赞

在 go 1.7 中,在 web 服务器上处理 mongo 会话的最惯用的方法是使用新的标准库包context编写一个中间件,该中间件可以在defer session.Close()调用请求上下文 Done() 时附加到。所以你不需要记得关闭


AttachDeviceCollection = func(next http.Handler) http.Handler {

        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

            db, err := infra.Cloner()

            if err != nil {

                http.Error(w, err.Error(), http.StatusInternalServerError)

                return

            }

            collection, err := NewDeviceCollection(db)


            if err != nil {

                db.Session.Close()

                http.Error(w, err.Error(), http.StatusInternalServerError)

                return

            }

            ctx := context.WithValue(r.Context(), DeviceRepoKey, collection)

            go func() {

                select {

                case <-ctx.Done():

                    collection.Session.Close()

                }

            }()


            next.ServeHTTP(w, r.WithContext(ctx))

        })

    }



查看完整回答
反对 回复 2021-08-23
  • 3 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信