mongodb - mgo go 服务器中打开的文件太多

标签 mongodb ubuntu go mgo

我在日志中收到这些错误:

Accept error: accept tcp [::]:80: accept4: too many open files;

用于 ubuntu 上的 mongodb 服务器,使用 mgo 编写。它们在运行大约一天后开始出现。

代码:

package main

import (
    "encoding/json"
    "io"
    "net/http"

    "gopkg.in/mgo.v2/bson"
)

var (
    Database *mgo.Database
)

func hello(w http.ResponseWriter, r *http.Request) {
    io.WriteString(w, "hello")
}

func setTile(w http.ResponseWriter, r *http.Request) {
    var requestJSON map[string]interface{}
    err := json.NewDecoder(r.Body).Decode(&requestJSON)
    if err != nil {
        http.Error(w, err.Error(), 400)
        return
    }

    collection := Database.C("tiles")

    if requestJSON["tileId"] != nil {
        query := bson.M{"tileId": requestJSON["tileId"]}
        collection.RemoveAll(query)
        collection.Insert(requestJSON)

        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        js, _ := json.Marshal(map[string]string{"result": "ok"})
        w.Write(js)
    } else {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        w.Write(js)
    }
}

func getTile(w http.ResponseWriter, r *http.Request) {
    var requestJSON map[string]interface{}
    err := json.NewDecoder(r.Body).Decode(&requestJSON)
    if err != nil {
        http.Error(w, err.Error(), 400)
        return
    }

    collection := Database.C("tiles")

    var result []map[string]interface{}

    if requestJSON["tileId"] != nil {
        query := bson.M{"tileId": requestJSON["tileId"]}
        collection.Find(query).All(&result)
    }

    if len(result) > 0 {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        js, _ := json.Marshal(result[0])
        w.Write(js)
    } else {
        w.WriteHeader(200)
        w.Header().Set("Content-Type", "application/json")
        js, _ := json.Marshal(map[string]string{"result": "tile id not found"})
        w.Write(js)
    }
}

func main() {
    session, _ := mgo.Dial("localhost")
    Database = session.DB("mapdb")

    mux := http.NewServeMux()
    mux.HandleFunc("/", hello)
    mux.HandleFunc("/setTile", setTile)
    mux.HandleFunc("/getTile", getTile)
    http.ListenAndServe(":80", mux)
}

里面有什么东西需要关闭吗?或者它的结构在某种程度上是错误的?

似乎有很多地方可以设置打开文件的限制,所以我不确定如何找出实际的限制。但似乎增加限制无论如何都不是问题,肯定会根据每个请求打开而不是关闭某些东西。

最佳答案

这不是您在 Go 中存储和使用 MongoDB 连接的方式。

你必须存储一个 mgo.Session ,不是 mgo.Database实例。每当您需要与 MongoDB 交互时,您都会获取 session 的副本或克隆(例如使用 Session.Copy()Session.Clone() ),并在不需要时关闭它(最好使用 延迟 声明)。这将确保您不会泄漏连接。

您还虔诚地省略了错误检查,请不要那样做。无论返回什么error,都要检查它并正确地采取行动(至少你可以做的是打印/记录它)。

所以基本上你需要做的是这样的:

var session *mgo.Session

func init() {
    var err error
    if session, err = mgo.Dial("localhost"); err != nil {
        log.Fatal(err)
    }
}

func someHandler(w http.ResponseWriter, r *http.Request) {
    sess := session.Copy()
    defer sess.Close() // Must close!

    c := sess.DB("mapdb").C("tiles")
    // Do something with the collection, e.g.
    var tile bson.M
    if err := c.FindId("someTileID").One(&result); err != nil {
        // Tile does not exist, send back error, e.g.:
        log.Printf("Tile with ID not found: %v, err: %v", "someTileID", err)
        http.NotFound(w, r)
        return
    }
    // Do something with tile
}

查看相关问题:

mgo - query performance seems consistently slow (500-650ms)

Concurrency in gopkg.in/mgo.v2 (Mongo, Go)

关于mongodb - mgo go 服务器中打开的文件太多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47179890/

相关文章:

mongodb - Grails过渡属性无法验证错误?

javascript - 范围错误 : Invalid status code: 0

linux - Ubuntu DHCP 中央服务器

json - Golang 返回嵌套的 JSON

node.js - Mongodb 多对多关系

mongodb - 由于超时,UpdateOne 在客户端失败,但 MongoDB 仍然处理它

c - 为什么即使在重新启动后,从 shell 更改时区也不会影响 gettimeofday() ?

ubuntu - Devstack 安装失败 : stack. sh failed 退出时出错

php - 无法通过PHP shell_exec在Apache下运行go二进制文件

Go 中的 XML - 如何获取任一标记并将其与结构的字段匹配?