当前位置: 首页 > 知识库问答 >
问题:

出现错误时重新创建mgo会话(读取tcp 127.0.0.1:46954->127.0.0.1:27017:i/o超时)

壤驷鸿
2023-03-14

我想知道在使用mgo的Go中如何管理MongoDB会话,尤其是如何正确地确保会话关闭,以及如何在写入失败时做出反应。

我阅读了以下内容:

维持mgo会议的最佳实践

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

不过,我还是无法将其应用于我的情况。

我有两个Goroutine,它们将一个又一个事件存储到MongoDB中,共享相同的*mgo。Session,两者看起来都像下面这样:

func storeEvents(session *mgo.Session) {
    session_copy := session.Copy()
    // *** is it correct to defer the session close here? <-----
    defer session_copy.Close()
    col := session_copy.DB("DB_NAME").C("COLLECTION_NAME")
    for {
        event := GetEvent()
        err := col.Insert(&event)
        if err != nil {
            // *** insert FAILED - how to react properly? <-----
            session_copy = session.Copy()
            defer session_copy.Close()
        }
    }
}

上校插页(

read tcp 127.0.0.1:46954->127.0.0.1:27017: i/o timeout

我不确定该如何应对。这个错误发生后,所有后续的写入都会发生,因此我似乎必须创建一个新的会话。我的选择似乎是:

1) 重新启动整个goroutine,即。

if err != nil {
    go storeEvents(session)
    return
}

2) 创建新会话副本

if err != nil {
    session_copy = session.Copy()
    defer session_copy.Close()
    col := session_copy.DB("DB_NAME").C("COLLECTION_NAME")
    continue
}

--

还有其他选择吗?

共有1个答案

邰英毅
2023-03-14

所以我不知道这是否会对你有任何帮助,但我对这个设置没有任何问题。

我有一个mongo软件包,我是从那里进口的。这是我的mongo的模板。归档

package mongo

import (
    "time"

    "gopkg.in/mgo.v2"
)

var (
    // MyDB ...
    MyDB DataStore
)

// create the session before main starts
func init() {
    MyDB.ConnectToDB()
}

// DataStore containing a pointer to a mgo session
type DataStore struct {
    Session *mgo.Session
}

// ConnectToTagserver is a helper method that connections to pubgears' tagserver
// database
func (ds *DataStore) ConnectToDB() {
    mongoDBDialInfo := &mgo.DialInfo{
        Addrs:    []string{"ip"},
        Timeout:  60 * time.Second,
        Database: "db",
    }
    sess, err := mgo.DialWithInfo(mongoDBDialInfo)
    if err != nil {
        panic(err)
    }
    sess.SetMode(mgo.Monotonic, true)
    MyDB.Session = sess
}

// Close is a helper method that ensures the session is properly terminated
func (ds *DataStore) Close() {
    ds.Session.Close()
}

然后,在另一个包中,例如,根据下面的评论更新main

package main

import (
    "../models/mongo"
)

func main() {
    // Grab the main session which was instantiated in the mongo package init function
    sess := mongo.MyDB.Session
    // pass that session in
    storeEvents(sess)
}

func storeEvents(session *mgo.Session) {
    session_copy := session.Copy()
    defer session_copy.Close()

    // Handle panics in a deferred fuction
    // You can turn this into a wrapper (middleware)
    // remove this this function, and just wrap your calls with it, using switch cases
    // you can handle all types of errors
    defer func(session *mgo.Session) {
        if err := recover(); err != nil {
            fmt.Printf("Mongo insert has caused a panic: %s\n", err)
            fmt.Println("Attempting to insert again")
            session_copy := session.Copy()
            defer session_copy.Close()
            col := session_copy.DB("DB_NAME").C("COLLECTION_NAME")
            event := GetEvent()
            err := col.Insert(&event)
            if err != nil {
                fmt.Println("Attempting to insert again failed")
                return
            }
            fmt.Println("Attempting to insert again succesful")
        }
    }(session)

    col := session_copy.DB("DB_NAME").C("COLLECTION_NAME")
    event := GetEvent()
    err := col.Insert(&event)
    if err != nil {
        panic(err)
    }
}

我在AWS上的生产服务器上使用了类似的设置。我每小时插入超过100万条。希望这有帮助。我为确保mongo服务器能够处理连接而做的另一件事是在我的生产机器上增加ulimit。在这一堆中讨论过

 类似资料:
  • 问题内容: 我正在通过mgo运行地图缩减任务。它运行在具有超过350万条记录的集合上。由于某些原因,我现在无法将此端口移植到聚合中。可能会晚一些。因此,map- reduce是我期待的事情。当我从为测试代码和输出而创建的原始js文件运行该作业时,它运行良好。我试图将地图和减少代码放在两个字符串中,然后尝试调用mgo.MapReduce为我做地图减少,以便在其他集合中编写输出。它给了我 读取TCP

  • 我返回了一个代码,使用jsoup-1.7.3.jar读取网页,它对一些网站有效,但对一些URL显示读取超时错误。 线程“main”java.net.SocketTimeoutException中的异常:java.net.SocketInputStream.socketRead0(本机方法)处java.net.SocketInputStream.Read(SocketInputStream.java

  • 当我调用restendpoint(rest模板http客户端)“myservice..com/rest/api/”时,有时会出现以下错误。此错误的原因是什么?这是客户端还是服务器错误?

  • 我想创建一个在MySQL中拥有自己数据库所有权限的用户。 当我使用这个用户创建一个表时,MySQL返回SQL server正在使用只读选项运行。 但是,当我改变到另一个现有用户的所有权限上,我可以创建表没有错误。 我想知道只读选项是全局的还是什么? 以下是我使用MySQL root的MySQL命令: 然后我切换到用户"demo": 所以我检查了只读选项,它似乎是打开的。 然而,我尝试使用另一个用户

  • 我已经用谷歌搜索了它。但是这些都不能解决我的问题。我在调用rest控件时,代码中的SSL证书出现了问题。 我的控制方法是: 错误为:-I/O错误在“https://myurl.com”的POST请求上:sun.security.validator.validatoreXception:PKIX路径构建失败:sun.security.provider.certpath.suncertPathBuil

  • 我正在尝试使用Spring Data Redis绝地组合连接到AWS ElastiCache Redis。[Redis Cluster enabled,因此它有Cluster Config endpoint,有3个碎片-每个碎片有1个主节点和2个副本节点] 读取超时错误。 AWS Redis服务器版本:5.0.3/群集模式:已启用/SSL:已启用/Auth:已启用(通过密码) 库——Spring数