我应该为mgo中的每个操作复制会话吗?

我想要upsert一个记录列表,所以我有两个选择,一个只使用一个会话,另一个为每个记录复制一个会话。所以,在我看来,第一种方法可能比第二种方法慢,但第一种方法会导致创建过多的会话吗?


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.复制每条记录的会话


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中调用这个方法:


for _, item := range cvMeasure.GetJobList() {

    err = this.SetCvJobItemMeasure(accessToken, versionPolicy, item)

    if nil != err {

        return

    }

}


慕田峪7331174
浏览 196回答 2
2回答

红颜莎娜

首先,我们需要看看mgo.Session.Copy()和mgo.Session.Clone()之间的区别。当go.Session.Clone()返回一个新会话时,该会话使用相同的套接字连接。这不一定是坏事,但请记住,在服务器端,每个连接分配一个堆栈。所以会话将共享相同的堆栈。根据您的用例,这可能会产生很大的不同。这就是问题所在——如果你为每条记录打开一个新的套接字连接,这会导致三向握手,这很慢。重用相同的套接字减少了这种开销,但仍然存在一些并且具有上述缺点。我倾向于做的是为每个长时间运行的工作单元建立一个新连接。一个简单的例子说明了这一点:package mainimport (    "fmt"    mgo "gopkg.in/mgo.v2"    bson "gopkg.in/mgo.v2/bson"    "net/http")var (    Database *mgo.Database)// The listEntries lists all postsfunc 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中的连接池来提高性能。一台 mongo 服务器的默认限制是 4096,以防止连接过多。func newSession(consistency Mode, cluster *mongoCluster, timeout time.Duration) (session *Session) {    cluster.Acquire()    session = &Session{        cluster_:    cluster,        syncTimeout: timeout,        sockTimeout: timeout,        poolLimit:   4096,    }    debugf("New session %p on cluster %p", session, cluster)    session.SetMode(consistency, true)    session.SetSafe(&Safe{})    session.queryConfig.prefetch = defaultPrefetch    return session}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go