mgo go 服务器中打开的文件太多 [英] too many open files in mgo go server

查看:30
本文介绍了mgo go 服务器中打开的文件太多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm getting these errors in the logs:

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

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

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

for a mongodb server on ubuntu, written in go using mgo. They start appearing after it's been running for about a day.

代码:

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

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

Is there something in there that needs closing? Or is it structured wrong in some way?

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

There seems to be lots of places to set the open file limits, so i'm not sure how to find out what the limits actually are. But it seems like increasing the limit isn't the problem anyway, surely something is being opened on every request and not closed.

推荐答案

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

This is not how you store and use a MongoDB connection in Go.

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

You have to store an mgo.Session, not an mgo.Database instance. And whenever you need to interact with the MongoDB, you acquire a copy or a clone of the session (e.g. with Session.Copy() or Session.Clone()), and you close it when you don't need it (preferable using a defer statement). This will ensure you don't leak connections.

您也宗教上忽略了错误检查,请不要这样做.无论返回什么error,都要检查它并正确处理它(至少你能做的就是打印/记录它).

You also religiously omit checking for errors, please don't do that. Whatever returns an error, do check it and act on it properly (the least you can do is print / log it).

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

So basically what you need to do is something like this:

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 - 查询性能似乎一直很慢 (500-650ms)

gopkg.in/mgo.v2 中的并发(蒙戈,去)

这篇关于mgo go 服务器中打开的文件太多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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