# #go #go-echo
Вопрос:
У меня есть API в GO, использующий echo и SQL Server в качестве базы данных.
Я использую db.Ping()
в начале каждой конечной точки, чтобы проверить, подключена ли бд по-прежнему или нет, это продолжает открывать новые подключения к бд с новыми сокетами, что в конечном итоге приводит к ошибке открытия слишком большого количества файлов.
db.Stats()
возвращает это {"MaxOpenConnections":0,"OpenConnections":413,"InUse":413,"Idle":0,"WaitCount":0,"WaitDuration":0,"MaxIdleClosed":2,"MaxIdleTimeClosed":62,"MaxLifetimeClosed":0}
Количество открытых соединений продолжает увеличиваться, даже несмотря на то, что количество активных запросов намного меньше этого.
Вот пример фрагмента:
package main
import (
"database/sql"
"github.com/labstack/echo/v4"
_ "github.com/denisenkom/go-mssqldb"
)
var db *sql.DB
func main () {
db, err = sql.Open("sqlserver", "sqlserver://username:passwrod@[server]?database=[db]amp;connection timeout=1000")
if err != nil {
log.Fatal(err)
}
db.SetConnMaxLifetime(10 * time.Minute)
db.SetConnMaxIdleTime(15 * time.Second)
e := echo.New()
e.GET("/", func(c echo.Context) error {
err := db.Ping()
if err != nil {
return echo.NewHTTPError(500, err)
}
var name string
err = db.QueryRow("select top 1 name from Test_Table;").Scan(amp;name)
if err != nil {
return echo.NewHTTPError(500, err)
}
return c.HTML(http.StatusOK, name)
})
e.Logger.Fatal(e.Start(":4000"))
}
Комментарии:
1. Это все ваше приложение? Если это так, то с кодом проблем нет. Возможно, проблема с водителем. Но если это не все ваше приложение и есть другие места, где
db
оно используется, то у нас нет возможности точно узнать, что не так. Однако распространенной проблемой является отсутствие закрытия*sql.Rows
или других ресурсов, связанных с БД.2. Это может произойти, если вы не закрываете ресурсы dl (в основном *sql.Rows, как упоминалось @mkopriva). Это также может произойти, если серверу БД требуется слишком много времени для отправки ответа, а клиент ожидает этих ответов. Если вы хотите, вы можете использовать db.SetMaxOpenConnections (), чтобы ограничить количество сокетов для сервера бд.
3. @mkopriva Должен ли я позвонить
defer rows.Close()
послеQuery()
, чтобы закрыть его, или мне следует закрыть его после того, как я просмотрю все необходимые строки?4. После того, как вы вызовете запрос и подтвердите, что значение ошибки равно нулю.