亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

我應該為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條經驗 獲得超13個贊

首先,我們需要看看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 關注
  • 218 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號