所以我在查找使用MongoDB的并发性的最佳实践方面遇到了一些麻烦。我第一次获得会话的实现看起来像这样:
var globalSession *mgo.Session
func getSession() (*mgo.Session, error) {
//Establish our database connection
if globalSession == nil {
var err error
globalSession, err = mgo.Dial(":27017")
if err != nil {
return nil, err
}
//Optional. Switch the session to a monotonic behavior.
globalSession.SetMode(mgo.Monotonic, true)
}
return globalSession.Copy(), nil
}
这很有效我遇到的麻烦是mongo有204个连接的限制然后它开始拒绝连接connection refused because too many open connections: 204
;但问题是因为我只调用它session.Copy()
返回会话而不是错误。所以事件虽然连接拒绝我的程序永远不会抛出错误。
现在我要做的只是有一个会话并使用它而不是复制,所以我可以访问连接错误,如下所示:
var session *mgo.Session = nil
func NewSession() (*mgo.Session, error) {
if session == nil {
session, err = mgo.Dial(url)
if err != nil {
return nil, err
}
}
return session, nil
}
现在我遇到的问题是,我不知道如果我尝试同时使用同一个会话会发生什么。
答案 0 :(得分:1)
关键是复制会话,然后在完成后关闭它。
func GetMyData() []myMongoDoc {
sessionCopy, _ := getSession() // from the question above
defer sessionCopy.Close() // this is the important bit
results := make([]myMongoDoc, 0)
sessionCopy.DB("myDB").C("myCollection").Find(nil).All(&results)
return results
}
说过看起来mgo实际上并没有暴露对底层连接的控制(参见维护库的Gustavo Niemeyer的评论)。会话几乎等同于连接,但即使您在会话上调用Close()
mgo也会保持连接活动。通过阅读它似乎可能是Clone()
的方式,因为它重用底层套接字,这将避免创建新套接字的3次握手(有关差异的更多讨论,请参阅here )。
另请参阅此SO answer,其中描述了处理会话的标准模式。