Go Lang 和 Labix mgo - 在后续请求后获取 EOF

Go Lang and Labix mgo - getting EOF after subsequent requests

我有一个网络进程,类似于

func main() {
    // mgo
    mongoDatabase, err := mgopath.Connect(envMongoPath)
    if err != nil {
        log.Fatal(err)
    }

    r := mux.NewRouter()
    // ....
    r.HandleFunc("/apps/{app:.+}", stuffHandler(mongoDatabase)).Methods("GET")
    http.Handle("/", r)

    listen := fmt.Sprintf("%s:%s", host, port)
    log.Fatal(http.ListenAndServe(listen, nil))
}

而 mgopath.Connect 看起来像

func Connect(mongoPath string) (*mgo.Database, error) {
    dbConfig, err := url.Parse(mongoPath)
    if err != nil {
        return nil, err
    }

    log.Printf("Connecting to %s", dbConfig.Host)
    sess, err := mgo.Dial(dbConfig.Host)
    if err != nil {
        return nil, err
    }

    dbName := dbConfig.Path
    log.Printf("Using database %s", dbName)
    if len(dbName) < 2 {
        return nil, errors.New("No database name specified.")
    }

    dbName = dbConfig.Path[1:len(dbConfig.Path)]
    return sess.DB(dbName), err
}

在路上的某个地方:

c := database.C("stuff")
err = c.Find(bson.M{"id": id}).One(&item) // First ~1-2 minutes work as expected, then I receive EOFs
// c.Insert(), c.Update(), c.All()...

问题是,几分钟后,所有对 mongodb return 的查询都出现错误 EOF。我必须重新启动该过程才能使事情重新开始。在 Mac 和 Windows 上(更频繁地)遇到了这两个问题。 MongoDB 在 Docker 内部运行,后者又在 boot2docker 内部运行。 VM 端口转发已经完成(这就是查询在一定时间内工作的原因)。

mgo 是否要求我在每次查询时都拨号?是否有一些我不知道的超时?

答案可以在这里找到:https://groups.google.com/forum/#!topic/mgo-users/XM0rc6p-V-8

There are two easy ways to get rid of the error:

1) Call Refresh on the session, which makes it discard (or put back in the pool, if the connection is good) the connection it's holding, and pick a new one when necessary.

2) Instead of using a single session, use many by calling session.Copy when you need a new session, and then call session.Close when you're done with it. This will also mean you're using multiple connections to the database, when necessary.

session.Copy 可能会创建很多连接到 mongodb,在大项目中,你可能会得到 "too many files open",所以你可以试试这个:

https://github.com/ti/mdb

如果您的连接不稳定,这将自动调用 session.refresh。

更少的连接和更少的错误,用于重试策略。