Closed rwynn closed 6 years ago
Hi @rwynn ,
Are you running it against a replica set? Could you check the connection count on the other secondaries please?
From mgo doc: In the Eventual consistency mode reads will be made to any secondary in the cluster, if one is available, and sequential reads will not necessarily be made with the same connection.
Hi @weiishann, I am running it against a single mongod instead, not a real replica set. Although I did call rs.initiate(), so I guess it's just a one node replicate set (which doesn't make any sense).
Anyway, I know this sort of setup is not how the Eventual Mode is supposed to run, since it is made to read from secondaries, however, I am still wondering why the difference in connection count, since even in the Eventual mode it should use the primary if a secondary is not available.
I guess what threw me is that I'm expecting to a new connection when (a) I copy the session or (b) I guess call SetMode with refresh = true, no matter what Mode the session is in. I'm seeing that happen with the default Mode, but not with Eventual.
Hi @rwynn
Would you be able to share your code? We're having a little trouble reproducing the issue.
Dom
Hi @domodwyer
The client code and the line number I had a question about is here
https://github.com/rwynn/gtm/blob/master/gtm.go#L925
That function should be getting called from another named DirectReadPaged
which first attempts to break a large collection into _id range segments which get read concurrently in multiple go routines in DirectReadSegment
.
Specifically, I am trying to use this library to read a large 20 million document collection. When I change the line above from mgo.Nearest
to mgo.Eventual
, then I see far fewer
connections in mongostat. I'm not sure if that is a bug or just a misunderstanding on my part.
A simple example of using this library can be found here
https://github.com/rwynn/gtm#usage https://github.com/rwynn/gtm#configuration
The DirectReadPaged function would then be triggered if db.users
is large collection (as configured in the 2nd example link)
A simple way to trigger is to run the following:
package main
import "github.com/globalsign/mgo"
import "github.com/rwynn/gtm"
func main() {
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
ctx := gtm.Start(session, >m.Options{
DirectReadNs: []string{"test.test"},
})
for {
select {
case <-ctx.ErrC:
break
case <-ctx.OpC:
break
}
}
}
Where test.test
is a large, multi-million document collection, and viewing the output of mongostat
.
Hi @rwynn
There doesn't seem to be an issue as such so I'm going to close this, but feel free to re-open if you come across a problem.
Dom
Hi @domodwyer,
Maybe this example is easier since it is a self contained program with output.
package main
import "github.com/globalsign/mgo"
import "github.com/globalsign/mgo/bson"
import "sync"
import "time"
import "fmt"
func printConns(wg *sync.WaitGroup, session *mgo.Session) {
defer wg.Done()
for {
status := bson.M{}
err := session.Run(bson.D{{"serverStatus", 1}}, &status)
if (err != nil) {
fmt.Printf("Error getting server status: %s\n", err)
} else {
fmt.Printf("Server connection status: %+v\n", status["connections"])
}
time.Sleep(time.Duration(5) * time.Second)
}
}
func runQuery(wg *sync.WaitGroup, session *mgo.Session) {
defer wg.Done()
mySession := session.Copy()
// TOGGLE FOLLOWING LINE AND COMPARE OUTPUT
// WITH LINE = less connections
// WITHOUT LINE = more connections
//mySession.SetMode(mgo.Eventual, true)
// END
defer mySession.Close()
for {
col := mySession.DB("test").C("test")
var results []bson.M
col.Find(nil).Limit(1).All(&results)
time.Sleep(time.Duration(5) * time.Second)
}
}
func main() {
wg := &sync.WaitGroup{}
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
for i:=0; i<20; i++ {
wg.Add(1)
go runQuery(wg, session)
}
wg.Add(1)
go printConns(wg, session)
wg.Wait()
}
If you run and note output, then un comment the line that sets the eventual mode, run and compare output.
Notice the difference in the number of connections reported. If you can explain to me why this difference is correct that would be helpful to me, because I would expect both to be equivalent. Thanks!
Thank for you maintaining mgo and adding new features. I had a question about setting the Mode of the session. I am using session.Copy() in a series of go routines to do work concurrently. I noticed that when I do this the number of connections goes up in mongostat. This looks good to me since I am trying to maximize throughput. However, if I follow the session.Copy() with a session.SetMode(mgo.Eventual, true), then I do not see the connection count increase in mongostat. I am trying to maximize read throughput and thought mgo.Eventual would be a faster mode to use, however I don't understand why this would not use a new socket. Is socket reuse the expected behavior in this case?
Without mgo.Eventual
With mgo.Eventual(refresh=true) added after the Copy, I only see about 5 conns instead of 29.