我应该为mgo中的每个操作复制会话吗? [英] Should I copy session for each operation in mgo?

查看:44
本文介绍了我应该为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
    }
}

推荐答案

首先,我们需要了解

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆