我应该为mgo中的每个操作复制会话吗? [英] Should I copy session for each operation in mgo?
问题描述
我想 upsert
一个记录列表,所以我有两种选择,一种是只使用一个会话,另一种是为每条记录复制一个会话.因此,我认为第一种方法可能比第二种方法慢,但是第一种方法会导致创建过多的会话吗?
I want to upsert
a list of record, so I have two choice, one just use one session, another copy a session for every record. So, as my opinion, first method may slower than the second, but will the first one cause too many session created?
1.使用一个会话
func (this *CvStoreServiceImpl) SetCvJobItemMeasureList(accessToken *base_datatype.ServiceAccessToken, versionPolicy string, jobItemList []*cv_common_type.CvJobItemMeasure) (err error) {
session := this.session.Clone()
defer session.Close()
for _, jobItem := range jobItemList {
objKey := &orm.ItemIdKey{
VersionName: versionPolicy, //XXX
ItemId: jobItem.ItemId,
}
obj := orm.ConvertToCvJobItemMeasureObj(versionPolicy, jobItem)
_, err2 := this.jobMeasureCollection.With(session).Upsert(objKey, obj)
if nil != err2 {
err = &common_error.NamedError{err2.Error()}
this.logger.Println(err2.Error())
}
}
return
}
每条记录的2.copy会话
2.copy session for every record
func (this *CvStoreServiceImpl) SetCvJobItemMeasure(accessToken *base_datatype.ServiceAccessToken, versionPolicy string, jobItem *cv_common_type.CvJobItemMeasure) (err error) {
session := this.session.Clone()
defer session.Close()
objKey := &orm.ItemIdKey{
VersionName: versionPolicy, //XXX
ItemId: jobItem.ItemId,
}
obj := orm.ConvertToCvJobItemMeasureObj(versionPolicy, jobItem)
_, err2 := this.jobMeasureCollection.With(session).Upsert(objKey, obj)
if nil != err2 {
err = &common_error.NamedError{err2.Error()}
return
}
return
}
然后在forloop中调用此方法:
then call this method in forloop:
for _, item := range cvMeasure.GetJobList() {
err = this.SetCvJobItemMeasure(accessToken, versionPolicy, item)
if nil != err {
return
}
}
推荐答案
首先,我们需要了解 mgo.Session.Clone().当 go.Session.Clone()
返回一个新的会话时,该会话使用相同的套接字连接.这不一定是一件坏事,但请记住,在服务器端,每个连接都会分配一个栈 .因此,会话将共享同一堆栈.根据您的用例,可能会有很大的不同.
First of all, we need to see the difference between mgo.Session.Copy() and mgo.Session.Clone(). While go.Session.Clone()
returns a new session, the session uses the same socket connection. That isn't necessarily a bad thing, but keep in mind that on the server side, a stack is allocated per connection. So the sessions would share the same stack. Depending on your use cases, that may make a big difference.
这是问题所在–如果为每个记录打开一个新的套接字连接,则会导致三向握手,这很慢.重用相同的套接字可以减少这种开销,但是仍然存在一些缺点,并且存在上述缺点.
And here is the problem – if you open a new socket connect for each record, this leads to a three way handshake, which is slowish. Reusing the same socket reduces this overhead, but there still is some and has the drawback described above.
我倾向于做的是在每个长期运行的工作单元中建立一个新的连接.一个简单的例子说明了这一点:
What I tend to do is to establish a new connection per long(er) running unit of work. A simple example illustrates this:
package main
import (
"fmt"
mgo "gopkg.in/mgo.v2"
bson "gopkg.in/mgo.v2/bson"
"net/http"
)
var (
Database *mgo.Database
)
// The listEntries lists all posts
func listPosts(w http.ResponseWriter, r *http.Request) {
// We have a rather long running unit of work
// (reading and listing all posts)
// So it is worth copying the session
collection := Database.C("posts").With( Database.Session.Copy() )
post := bson.D{}
posts := collection.Find(bson.M{}).Iter()
for posts.Next(&post) {
// Process posts and send it to w
}
}
func main() {
session, _ := mgo.Dial("mongodb://localhost:27017")
Database := session.DB("myDb")
// Count is a rather fast operation
// No need to copy the session here
count, _ := Database.C( "posts" ).Count()
fmt.Printf("Currently %d posts in the database", count )
http.HandleFunc("/posts", listPosts)
http.ListenAndServe(":8080", nil)
}
这篇关于我应该为mgo中的每个操作复制会话吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!