英文:
Concurrency in gopkg.in/mgo.v2 (Mongo, Go)
问题
我希望在使用Go编写的Web应用程序中使用MongoDB。
我可以拥有一个mgo.Session
并在Web应用程序中并发使用它吗?例如在http.Handler
中。
还是我应该调用Session.Copy
和Session.Close
来创建会话池?
听起来有些矛盾,我在某些地方读到mgo.Session
内部已经实现了连接池,可以并发使用会话,而在其他地方我读到需要使用Copy
和Close
。
英文:
I wish to use MongoDB in webapp written in Go.
Can I have one mgo.Session
and use it concurrently in web app. e.g. in http.Handler
or should I call Session.Copy
and Session.Close
-> make pool 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
.
答案1
得分: 9
mgo.Session
是线程安全的。引用它的文档:
> 所有的 Session 方法都是线程安全的,可以从多个 goroutine 中调用。
但这并不意味着你不应该在并行中创建和使用更多的 Session,通过调用 Session.Copy()
或 Session.Clone()
,在初始的 dial 时间获取的 Session 上。
线程安全和使用更多 Session 的好处并不互斥。虽然你可以从任意数量的 goroutine 中使用单个 mgo.Session
,但这样做不会很好地扩展,甚至根本不会扩展。Session 自动管理一个连接池,甚至可能连接到多个服务器节点,但如果你使用单个 Session,你就无法利用这一点。通过在每个请求开始时创建一个新的 Session(如果需要),并在结束时正确关闭它(使用 Session.Close()
,最好使用 defer
调用),你可以利用同时使用多个连接的潜力,可能连接到多个服务器节点(如果可用),从而更好地利用服务器资源,并获得更快的响应时间(无论是从数据库还是最终传递给 HTTP 终端用户)。调用 Session.Close()
不会关闭与服务器的底层连接,它只会将连接放回连接池,准备好供另一个 Session 使用。
还可以参考关于使用 Session
的相关问题:https://stackoverflow.com/questions/40999637/mgo-query-performance-seems-consistently-slow-500-650ms/41000876#41000876
英文:
The mgo.Session
is safe for concurrent use. Quoting from its doc:
> All Session methods are concurrency-safe and may be called from multiple goroutines.
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.
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. 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. 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; and getting faster response times (both from the database, and ultimately to your HTTP end users). 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.
Also see related question about the use of Session
s: https://stackoverflow.com/questions/40999637/mgo-query-performance-seems-consistently-slow-500-650ms/41000876#41000876
答案2
得分: 4
调用Dial
、DialWithTimeout
或DialWithInfo
将建立连接池。如果您需要多个会话,则需要调用session.Copy()
或session.New()
,推荐使用session.Copy()
,因为它将保留授权信息。以下是一个示例:
假设您有一个UserService
结构体来处理所有用户数据库需求。请注意,这是我凭记忆写的,所以可能有一些语法错误,但思路是正确的。
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
}
}
以上是一个示例代码。
英文:
Calling Dial
or DialWithTimeout
or DialWithInfo
will establish the connection pool. 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. Here is an example:
Lets say you have a UserService
struct to handle all your user db needs. 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
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论