在Go中“显式关闭”mgo MongoDB
我有一个Docker集群,运行10个相同类型的web服务。他们都在使用MongoDB,以及其他用于数据持久性的工具 这是在服务启动时从main调用的代码:在Go中“显式关闭”mgo MongoDB,mongodb,go,mgo,Mongodb,Go,Mgo,我有一个Docker集群,运行10个相同类型的web服务。他们都在使用MongoDB,以及其他用于数据持久性的工具 这是在服务启动时从main调用的代码: // Init establishes a connection with MongoDB instance. func Init(mongoURL string) *mgo.Session { mongo, err := mgo.Dial(mongoURL) misc.PanicIf(err) // make su
// Init establishes a connection with MongoDB instance.
func Init(mongoURL string) *mgo.Session {
mongo, err := mgo.Dial(mongoURL)
misc.PanicIf(err)
// make sure we are strongly consistent
mongo.SetMode(mgo.Strong, true)
// update global state
db = mongo
Entries = db.DB("").C("entries")
Channels = db.DB("").C("channels")
Settings = db.DB("").C("settings")
Metadata = db.DB("").C("metadata")
// only use this on first load, to confirm the settings are there
// every refresh should be done via UpdateGlobalSettings (thread-safe)
GlobalSettings = &GlobalSettingsStruct{}
GlobalSettings.Init()
return mongo
}
因此,基本上API和Worker只使用全局变量,如条目、设置等
运行一段时间后,服务停止正常工作。每个mongo操作,例如条目。查找。。。返回错误:显式关闭
这是什么意思?我应该定期刷新mongoDB连接,还是应该关闭它并与每个请求重新建立连接
该应用程序以性能为导向,因此,尽管mongo连接已关闭,但由于所有内容都在内存或群集缓存中运行,因此所有内容仍在运行。我不想做一些会延迟处理的愚蠢的事情。首先,尝试在mgo中启用调试模式,以便获得有关正在发生的事情的更多信息 我认为服务器在一段不活动时间后正在断开连接。 在任何情况下,通常的方法是进行mgo拨号,然后在每个请求开始时使用中间件复制连接 皮埃特罗没关系。而是使用Session.Copy创建新的连接实例,而不是直接使用返回的会话。golang mongodb驱动程序包中有连接池。当未使用sess.SetPoolLimit50时,当mgo处于压力下时会发生许多错误,例如10.000个并发连接 当我限制游泳池时,错误消失了 我已经为下面这个问题创建了一个测试用例源代码,所以您可以在自己的机器上轻松地测试它 我想听听你对这种行为有什么建议
package main
import (
"fmt"
"time"
// you can also use original go-mgo/mgo here as well
mgo "github.com/globalsign/mgo"
"github.com/globalsign/mgo/bson"
)
// TODO: put some records into db first:
//
// use testapi
// db.competitions.insert([
// {game_id: 1, game_name: "foo"},
// {game_id: 2, game_name: "bar"},
// {game_id: 3, game_name: "jazz"}
// ])
// NOTE: you might want to increase this depending on your machine power
// mine is:
// MacBook (Retina, 12-inch, Early 2015)
// 1,2 GHz Intel Core M
// 8 GB 1600 MHz DDR3
const ops = 10000
type m bson.M
func main() {
sess, err := mgo.DialWithTimeout("localhost", time.Second)
if err != nil {
panic(err)
}
defer sess.Close()
// NOTE: without this setting there are many errors
// see the end of the file
// setting pool limit prevents most of the timeouts
// sess.SetPoolLimit(50)
// sess.SetSocketTimeout(60 * time.Second)
sess.SetMode(mgo.Monotonic, true)
time.Sleep(time.Second)
done := make(chan bool, ops)
for i := 0; i < ops; i++ {
go func() {
defer func() { done <- true }()
result, err := fetchSomething(sess)
if err != nil {
fmt.Printf("ERR: %s\n", err)
}
fmt.Printf("RESULT: %+v\n", result)
}()
}
for i := 0; i < ops; i++ {
<-done
}
}
func fetchSomething(sess *mgo.Session) ([]m, error) {
s := sess.Copy()
defer s.Close()
result := []m{}
group := m{
"$group": m{
"_id": m{
"id": "$game_id",
"name": "$game_name",
},
},
}
project := m{
"$project": m{
"_id": "$_id.id",
"name": "$_id.name",
},
}
sort := m{
"$sort": m{
"_id": 1,
},
}
err := col(s, "competitions").Pipe([]m{group, project, sort}).All(&result)
if err != nil {
return nil, err
}
return result, nil
}
// col is a helper for selecting a column
func col(sess *mgo.Session, name string) *mgo.Collection {
return sess.DB("testapi").C(name)
}
/*
ERRORS WITHOUT sess.SetPoolLimit(50)
$ go run socket_error.go
RESULT: [map[name:foo _id:1] map[_id:2 name:bar] map[_id:3 name:jazz]]
ERR: read tcp 127.0.0.1:52918->127.0.0.1:27017: read: connection reset by peer
ERR: write tcp 127.0.0.1:52084->127.0.0.1:27017: write: broken pipe
RESULT: []
RESULT: []
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
RESULT: []
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
RESULT: []
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
RESULT: []
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
RESULT: []
ERR: write tcp 127.0.0.1:53627->127.0.0.1:27017: write: broken pipe
RESULT: []
RESULT: []
ERR: read tcp 127.0.0.1:53627->127.0.0.1:27017: read: connection reset by peer
RESULT: []
ERR: resetNonce: write tcp 127.0.0.1:53625->127.0.0.1:27017: write: broken pipe
RESULT: []
RESULT: [map[name:foo _id:1] map[_id:2 name:bar] map[_id:3 name:jazz]]
ERR: resetNonce: write tcp 127.0.0.1:54591->127.0.0.1:27017: write: broken pipe
RESULT: []
...
...
*/