我想我在 Golang 中管理數據庫連接池時遇到了嚴重的問題。我使用 Gorilla web 工具包構建了一個 RESTful API,當只有很少的請求被發送到服務器時,它工作得很好。但是現在我開始使用 loader.io 站點執行負載測試。我為這篇長文章道歉,但我想給你完整的圖片。在繼續之前,這里有一些關于運行 API 和 MySQL 的服務器的信息: Dedicated Hosting Linux 8GB RAM Go version 1.1.1 使用 go-sql-driver MySQL 5.1 的數據庫連接使用 loader.io 我可以毫無問題地發送 1000 個 GET 請求/15 秒。但是當我發送 1000 個 POST 請求/15 秒時,我收到很多錯誤,所有這些錯誤都是 ERROR 1040 數據庫連接過多。許多人在網上報告了類似的問題。請注意,我現在只測試一個特定的 POST 請求。對于這個帖子請求,我確保了以下內容(網上許多其他人也建議這樣做)我確保我不使用 Open 和 Close *sql.DB 作為短期函數。所以我只為連接池創建了全局變量,正如你在下面的代碼中看到的,盡管我在這里接受建議,因為我不喜歡使用全局變量。我確保在可能的情況下使用 db.Exec,并且只在預期結果時使用 db.Query 和 db.QueryRow。由于上面沒有解決我的問題,我嘗試設置db.SetMaxIdleConns(1000),它解決了1000個POST請求/15秒的問題。這意味著不再有 1040 個錯誤。然后我將負載增加到 2000 個 POST 請求/15 秒,我再次開始收到 ERROR 1040。我試圖增加 db.SetMaxIdleConns() 中的值,但這并沒有什么區別。這是我通過運行 SHOW STATUS WHERE variable_name= 'Threads_connected'從 MySQL 數據庫中獲得的連接數的一些連接統計信息;對于 1000 個 POST 請求/15 秒:觀察到 #threads_connected ~= 100 對于 2000 個 POST 請求/15 秒:觀察到 #threads_connected ~= 600我還在 my.cnf 中增加了 MySQL 的最大連接數,但這并沒有什么不同。你有什么建議?代碼看起來好嗎?如果是,那么可能是連接有限。您將在下面找到代碼的簡化版本。var db *sql.DBfunc main() { db = DbConnect() db.SetMaxIdleConns(1000) http.Handle("/", r) err := http.ListenAndServe(fmt.Sprintf("%s:%s", API_HOST, API_PORT), nil) if err != nil { fmt.Println(err) }}func DbConnect() *sql.DB { db, err := sql.Open("mysql", connectionString) if err != nil { fmt.Printf("Connection error: %s\n", err.Error()) return nil } return db}func PostBounce(w http.ResponseWriter, r *http.Request) { userId, err := AuthRequest(r) //error checking //ready requesy body and use json.Unmarshal bounceId, err := CreateBounce(userId, b) //return HTTP status code here}func AuthRequest(r *http.Request) (id int, err error) { //parse header and get username and password query := "SELECT Id FROM Users WHERE Username=? AND Password=PASSWORD(?)" err = db.QueryRow(query, username, password).Scan(&id) //error checking and return}
3 回答

慕尼黑的夜晚無繁華
TA貢獻1864條經驗 獲得超6個贊
Godatabase/sql
不會阻止您創建無限數量的數據庫連接。如果池中有空閑連接,則使用它,否則創建一個新連接。
因此,在負載下,您的請求處理程序 sql.DB 可能找不到空閑連接,因此在需要時會創建一個新連接。這會造成一些影響 - 在可能的情況下重用空閑連接并在需要時創建新連接 - 最終達到 Db 的最大連接數。而且,不幸的是,在 Go 1.1 中沒有一種方便的方法(例如SetMaxOpenConns)來限制打開的連接。
升級到較新版本的 Golang。在Go 1.2+ 中,你得到SetMaxOpenConns。并查看 MySql 文檔以開始設置然后進行調整。
db.SetMaxOpenConns(100) //tune this
如果你必須使用 Go 1.1,你需要確保你的代碼一次*sql.DB
只被 N 個客戶端使用。
- 3 回答
- 0 關注
- 270 瀏覽
添加回答
舉報
0/150
提交
取消