Go write unix /tmp/mysql.sock:在发送大量请求时断开管道

时间:2014-01-14 21:40:10

标签: mysql go

我有一个Go API端点,可以进行多个MySQL查询。当端点收到少量请求时,它可以正常工作。但是,我现在正在使用带有100个请求的apache bench来测试它。前100个都经过了。但是,第二个100导致出现此错误

    2014/01/15 12:08:03 http: panic serving 127.0.0.1:58602: runtime error: invalid memory address or nil pointer dereference
goroutine 973 [running]:
net/http.func·009()
    /usr/local/Cellar/go/1.2/libexec/src/pkg/net/http/server.go:1093 +0xae
runtime.panic(0x402960, 0x9cf419)
    /usr/local/Cellar/go/1.2/libexec/src/pkg/runtime/panic.c:248 +0x106
database/sql.(*Rows).Close(0x0, 0xc2107af540, 0x69)
    /usr/local/Cellar/go/1.2/libexec/src/pkg/database/sql/sql.go:1576 +0x1e
store.findProductByQuery(0xc2107af540, 0x69, 0x0, 0xb88e80, 0xc21000ac70)
    /Users/dennis.suratna/workspace/session-go/src/store/product.go:83 +0xe3
store.FindProductByAppKey(0xc210337748, 0x7, 0x496960, 0x6, 0xc2105eb1b0)
    /Users/dennis.suratna/workspace/session-go/src/store/product.go:28 +0x11c
api.SessionHandler(0xb9eff8, 0xc2108ee200, 0xc2108f5750, 0xc2103285a0, 0x0, ...)
    /Users/dennis.suratna/workspace/session-go/src/api/session_handler.go:31 +0x2fb
api.func·001(0xb9eff8, 0xc2108ee200, 0xc2108f5750, 0xc2103285a0)
    /Users/dennis.suratna/workspace/session-go/src/api/api.go:81 +0x4f
reflect.Value.call(0x3ad9a0, 0xc2101ffdb0, 0x130, 0x48d520, 0x4, ...)
    /usr/local/Cellar/go/1.2/libexec/src/pkg/reflect/value.go:474 +0xe0b
reflect.Value.Call(0x3ad9a0, 0xc2101ffdb0, 0x130, 0xc2103c4a00, 0x3, ...)
    /usr/local/Cellar/go/1.2/libexec/src/pkg/reflect/value.go:345 +0x9d
github.com/codegangsta/inject.(*injector).Invoke(0xc2103379c0, 0x3ad9a0, 0xc2101ffdb0, 0x4311a0, 0x1db94e, ...)

看起来它不是由并发请求的数量引起的,而是由于没有正确关闭的东西引起的。我已经关闭了我在代码中创建的每个准备语句。我想知道是否有人以前见过这个。

编辑: 这就是我初始化MySQL连接的方式:

func InitStore(environment string) error {
    db, err := sql.Open("mysql", connStr(environment))
    ....

    S = &Store{
        Mysql:       db,
        Environment: environment,
   }
}

在我启动服务器时只发生一次。

2 个答案:

答案 0 :(得分:1)

如果使用Go 1.2.x,则可以使用db.SetMaxOpenConns告诉sql包不要打开多于X个连接。在X连接已经打开(和忙)之后需要数据库连接的查询将阻塞,直到有可用的连接。

话虽如此:“堆栈跟踪”的下一行是什么?当您的服务函数失败时,http / server.go中的行~1093是恢复代码。它看起来更像是你只是错误地处理了一些数据而导致它失败,或者你错过了错误检查,然后在你真正返回错误时尝试处理数据等等。

答案 1 :(得分:1)

好的,所以我能够解决这个问题,现在我可以发送~500个请求,包含10个并发,不再有Broken pipeToo many connections error

我认为这一切都归结为遵循最佳实践。当您不希望向用户QueryRow而不是Query返回多行时,请将其与Scan链接

db.QueryRow(...).Scan(...)

如果您不希望返回行,并且您不打算重复使用语句,请使用Exec而不是Prepare

如果您已准备好语句或查询多行。不要忘记Close()

获得以上所有内容

https://github.com/go-sql-driver/mysql/issues/111