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
.
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: mgo - query performance seems consistently slow (500-650ms)
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With