亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Golang RESTful API 負載測試導致數據庫連接過多

Golang RESTful API 負載測試導致數據庫連接過多

Go
慕斯709654 2021-08-23 17:44:48
我想我在 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 個客戶端使用。


查看完整回答
反對 回復 2021-08-23
?
catspeake

TA貢獻1111條經驗 獲得超0個贊

需要注意的另一件事是將 my.cnf 文件中的 back_log 設置為更高的值,例如幾百或 1000。這將有助于每秒處理更多連接。請參閱每秒高連接數


查看完整回答
反對 回復 2021-08-23
  • 3 回答
  • 0 關注
  • 270 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號