goのsql/databaseの接続でやり方間違えると資源枯渇したりして大変らしいので負荷をかけてみた
- http://go-database-sql.org/surprises.html
- こちらのページに書かれている
Opening and closing databases can cause exhaustion of resources.
が気になったのでwrkで負荷をかけてみた。
条件
- dockerでmysqlを立ち上げる
- SelectとUpdateが単純に走るだけのhandlerを設置したgoのserverを立ち上げる
1. 最初にdbオブジェクトを初期化して持ち回す方法 2. リクエストのたびにdbオブジェクトをOpenする方法
上記2つを検証した
結論
wrk -c 2 -t 1 -d 30 http://localhost:8080/ping
- 上記の負荷に1のケースは耐えられたが、2のケースは
too many connections
を多発して耐えられなかった
追記のメモ
go run -gcflags '-m' main.go
- コンパイルオプションでheap調査が出来るんだけど
- 上の1のケースでも
leaking closure reference db
とか物騒な単語が出てくる - 本当にリークするのか、その可能性があるから警告してるのか
- 後者だと信じたいのでruntimeのコードを見た
2025 >...>...// Treat a captured closure variable as equivalent to the 2026 >...>...// original variable. 2027 >...>...if src.IsClosureVar() { 2028 >...>...>...if leaks && Debug['m'] != 0 { 2029 >...>...>...>...Warnl(src.Pos, "leaking closure reference %S", src) 2030 >...>...>...>...step.describe(src) 2031 >...>...>...} 2032 >...>...>...e.escwalk(level, dst, src.Name.Defn, e.stepWalk(dst, src.Name.Defn, "closure-var", step)) 2033 >...>...}
- なんとなくだけど、
IsClosureVar
がコードにあった場合に出してる警告ぽいので - 後者だと信じて寝ます