为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕田峪7331174 2021-11-15 20:45:38
我想要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    }}
查看完整描述

2 回答

?
红颜莎娜

TA贡献1842条经验 获得超12个赞

首先,我们需要看看mgo.Session.Copy()和mgo.Session.Clone()之间的区别。当go.Session.Clone()返回一个新会话时,该会话使用相同的套接字连接。这不一定是坏事,但请记住,在服务器端,每个连接分配一个堆栈。所以会话将共享相同的堆栈。根据您的用例,这可能会产生很大的不同。


这就是问题所在——如果你为每条记录打开一个新的套接字连接,这会导致三向握手,这很慢。重用相同的套接字减少了这种开销,但仍然存在一些并且具有上述缺点。


我倾向于做的是为每个长时间运行的工作单元建立一个新连接。一个简单的例子说明了这一点:


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)

}


查看完整回答
反对 回复 2021-11-15
?
波斯汪

TA贡献1811条经验 获得超4个赞

是的,复制一个会话来执行一个或几个操作是好的,让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

}


查看完整回答
反对 回复 2021-11-15
  • 2 回答
  • 0 关注
  • 195 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信