【问题标题】:too many open files in mgo go servermgo go服务器中打开的文件太多
【发布时间】:2017-11-08 12:35:20
【问题描述】:

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

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

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

代码:

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)
}

里面有什么东西需要关闭吗?还是在某些方面结构错误?

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

【问题讨论】:

    标签: mongodb ubuntu go mgo


    【解决方案1】:

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

    您必须存储mgo.Session,而不是mgo.Database 实例。每当您需要与 MongoDB 交互时,您都可以获得会话的副本或克隆(例如使用 Session.Copy()Session.Clone()),并在不需要时关闭它(最好使用 defer陈述)。这将确保您不会泄漏连接。

    你也宗教地省略了检查错误,请不要那样做。无论返回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)

    【讨论】:

      【解决方案2】:

      你不见了:

      defer r.Body.Close()
      

      确保在return语句之前使用它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-22
        相关资源
        最近更新 更多