同时在go中使用相同的mgo会话

时间:2015-09-25 17:56:11

标签: mongodb go concurrency mgo

所以我在查找使用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
}

现在我遇到的问题是,我不知道如果我尝试同时使用同一个会话会发生什么。

1 个答案:

答案 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,其中描述了处理会话的标准模式。