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

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

问题描述

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

I'm getting these errors in the logs:

接受错误:接受tcp [::]:80:接受4:打开的文件过多;

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天全站免登陆