我在日志中收到这些错误:
接受错误:接受tcp [::]:80:接受4:打开的文件过多;
对于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) }
那里有需要关闭的东西吗?还是某种程度上的结构错误?
似乎有很多地方可以设置打开文件的限制,所以我不确定如何找出限制。但是增加限制似乎并不是问题所在,肯定是在每个请求上都打开了一些东西而没有关闭它。
这不是您在Go中存储和使用MongoDB连接的方式。
您必须存储一个mgo.Session,而不是mgo.Database实例。而且,每当需要与MongoDB进行交互时,您都可以获取会话的副本或副本(例如,使用Session.Copy()或Session.Clone()),并在不需要时关闭它(最好使用defer语句)。这将确保您不会泄漏连接。
mgo.Session
mgo.Database
Session.Copy()
Session.Clone()
defer
您也 虔诚地 忽略检查错误,请不要这样做。不管返回什么error,都要检查并正确处理(至少可以做的是打印/记录它)。
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 }