简体   繁体   English

gopkg.in/mgo.v2中的并发(Mongo,Go)

[英]Concurrency in gopkg.in/mgo.v2 (Mongo, Go)

I wish to use MongoDB in webapp written in Go. 我希望在Go中编写的webapp中使用MongoDB。

Can I have one mgo.Session and use it concurrently in web app. 我可以拥有一个mgo.Session并在Web应用程序中同时使用它。 eg in http.Handler 例如在http.Handler

or should I call Session.Copy and Session.Close -> make pool of sessions. 或者我应该调用Session.CopySession.Close - > make session of sessions。

It sounds contradictory somewhere I read that pool is already implemented inside of mgo.Session and I can use session concurrently and in other places I read that I need Copy and Close . 这听起来很矛盾我读到池已经在mgo.Session实现了,我可以同时使用会话,在其他地方我读到我需要CopyClose

The mgo.Session is safe for concurrent use. mgo.Session对于并发使用是安全的。 Quoting from its doc: 引用其文档:

All Session methods are concurrency-safe and may be called from multiple goroutines. 所有Session方法都是并发安全的,可以从多个goroutine中调用。

But this doesn't mean you should not create and use more of them in parallel, by calling Session.Copy() or Session.Clone() , on the initial session obtained at dial time. 但这并不意味着您不应通过在拨号时获得的初始会话上调用Session.Copy()Session.Clone()来并行创建和使用更多的并行。

Being concurrency-safe and having benefit from using more of them do not exclude each other (they are not mutually exclusive ). 并发安全并且从使用更多它们中受益并不相互排斥 (它们不是相互排斥的 )。 While you may use a single mgo.Session from arbitrary number of goroutines, that will not scale well, that will not scale at all . 虽然你可以使用单个mgo.Session从够程的任意数,不会很好地扩展,这不会在所有规模。 Sessions automatically manage a pool of connections, maybe even to multiple server nodes, but if you're using a single Session , you're not taking advantage of that. 会话自动管理连接池,甚至可以管理多个服务器节点,但如果您使用单个Session ,则不会利用它。 By creating a new Session at the start of each of your request (if needed), and properly closing it at the end (with Session.Close() ; preferably called using defer ), you are taking advantage of potentially using multiple connections at the same time, possibly to multiple server nodes (if available), and thus better utilizing server resources; 通过在每个请求开始时创建一个新的Session (如果需要),并在最后正确地关闭它(使用Session.Close() ;最好使用defer调用),您可以利用可能在同时,可能到多个服务器节点(如果可用),从而更好地利用服务器资源; and getting faster response times (both from the database, and ultimately to your HTTP end users). 并获得更快的响应时间(从数据库,最终到您的HTTP最终用户)。 Calling Session.Close() does not close the underlying connection to the server, it will just put the connection back to the pool, ready to be picked up by another session. 调用Session.Close()不关闭与服务器的底层连接,它只是将连接放回池中,准备被另一个会话拾取。

Also see related question about the use of Session s: mgo - query performance seems consistently slow (500-650ms) 另请参阅有关Session s使用的相关问题: mgo - 查询性能似乎一直很慢(500-650ms)

Calling Dial or DialWithTimeout or DialWithInfo will establish the connection pool. 调用DialDialWithTimeoutDialWithInfo将建立连接池。 If you need more than one session then you need to call session.Copy() or session.New(), session.Copy() is preferred since it will retain the auth. 如果您需要多个会话,则需要调用session.Copy()或session.New(),session.Copy()是首选,因为它将保留auth。 Here is an example: 这是一个例子:

Lets say you have a UserService struct to handle all your user db needs. 假设您有一个UserService结构来处理所有用户数据库需求。 Note this is from the top of my head so there might be a few syntax errors but the idea is there. 请注意,这是我的头脑,所以可能会有一些语法错误,但这个想法就在那里。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM