在Go语言中同时使用相同的mgo会话(session)

huangapple go评论77阅读模式
英文:

Concurrently using the same mgo session in go

问题

所以我在使用Go语言与MongoDB并发时遇到了一些问题。我最初的获取会话的实现如下:

var globalSession *mgo.Session

func getSession() (*mgo.Session, error) {
    // 建立数据库连接
    if globalSession == nil {
        var err error
        globalSession, err = mgo.Dial(":27017")
        if err != nil {
            return nil, err
        }

        // 可选。将会话切换为单调行为。
        globalSession.SetMode(mgo.Monotonic, true)
    }

    return globalSession.Copy(), nil
}

这个方法很好用,但我遇到的问题是MongoDB有204个连接的限制,然后它开始拒绝连接,报错信息为connection refused because too many open connections: 204。然而,问题是由于我调用了session.Copy(),它只返回一个会话而不是错误。所以即使连接被拒绝,我的程序也没有抛出错误。

现在我考虑的是只使用一个会话,而不是使用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
}

现在我对此的问题是,如果我尝试并发使用同一个会话,会发生什么。

英文:

So I'm having some trouble figuring out best practices for using concurrency with a MongoDB in go. My first implementation of getting a session looked like this:

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
}

This works great the trouble I'm running into is that mongo has a limit of 204 connections then it starts refusing connections connection refused because too many open connections: 204;however, the issue is since I'm calling session.Copy() it only returns a session and not an error. So event though the connection refused my program never thrown an error.

Now what I though about doing is just having one session and using that instead of copy so I can have access to a connection error like so:

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
}

Now the problem I have with this is that I don't know what would happen if I try to make concurrent usage of that same session.

答案1

得分: 1

关键是复制会话,然后在使用完毕后关闭它。

func GetMyData() []myMongoDoc {
    sessionCopy, _ := getSession() // 来自上面的问题
    defer sessionCopy.Close() // 这是重要的部分

    results := make([]myMongoDoc, 0)
    sessionCopy.DB("myDB").C("myCollection").Find(nil).All(&results)
    return results
}

话虽如此,看起来 mgo 实际上并没有暴露对底层连接的控制(请参阅维护该库的 Gustavo Niemeyer 的评论)。一个会话基本上等同于一个连接,但即使在会话上调用 Close(),mgo 仍然保持连接处于活动状态。从周围的阅读中,似乎 Clone() 可能是一个可行的方法,因为它重用底层套接字,这将避免创建新套接字的三次握手(有关差异的更多讨论,请参见这里)。

还可以参考这个SO答案,描述了处理会话的标准模式。

英文:

The key is to duplicate the session and then close it when you've finished with it.

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
}

Having said that it looks like mgo doesn't actually expose control over the underlying connections (see the comment from Gustavo Niemeyer who maintains the library). A session pretty much equates to a connection, but even if you call Close() on a session mgo keeps the connection alive. From reading around it seems that Clone() might be the way to go, as it reuses the underlying socket, this will avoid the 3 way handshake of creating a new socket (see here for more discussion on the difference).

Also see this SO answer describing a standard pattern to handle sessions.

huangapple
  • 本文由 发表于 2015年9月26日 01:56:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/32787999.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定