Recibo estos errores en los registros:

Aceptar error: accept tcp [::]: 80: accept4: demasiados archivos abiertos;

Para un servidor mongodb en ubuntu, escrito en go usando mgo. Empiezan a aparecer después de que ha estado funcionando durante aproximadamente un día.

Código:

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

¿Hay algo ahí que necesite cerrarse? ¿O está mal estructurado de alguna manera?

Parece que hay muchos lugares para establecer los límites de archivos abiertos, por lo que no estoy seguro de cómo averiguar cuáles son realmente los límites. Pero parece que aumentar el límite no es el problema de todos modos, seguramente algo se abre en cada solicitud y no se cierra.

3
jonydep 8 nov. 2017 a las 15:35

2 respuestas

La mejor respuesta

No es así como almacena y usa una conexión MongoDB en Go.

Debe almacenar un mgo.Session, no un mgo.Database instancia. Y siempre que necesite interactuar con MongoDB, adquiere una copia o un clon de la sesión (por ejemplo, con Session.Copy() o {{X3 }}) y lo cierra cuando no lo necesita (es preferible usar una instrucción defer). Esto asegurará que no tenga fugas en las conexiones.

También religiosamente omite la comprobación de errores, por favor no lo haga. Lo que sea que devuelva un error, verifíquelo y actúe correctamente (lo mínimo que puede hacer es imprimirlo / registrarlo).

Entonces, básicamente, lo que debes hacer es algo como esto:

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
}

Ver preguntas relacionadas:

mgo: el rendimiento de las consultas parece constantemente lento (500-650 ms)

Concurrencia en gopkg.in/mgo.v2 (Mongo, Go)

4
icza 8 nov. 2017 a las 13:33

Estás perdido:

defer r.Body.Close()

Asegúrese de que se use antes de la declaración de devolución.

0
Prcela 6 may. 2020 a las 13:29