#初めに
GCPをつかっていてコネクションプールの話に行き着きました。
「最大コネクション数が100を超えました」というエラーが発生。
なぜコネクション数が多くなってしまうのかを調べ、見つけた対処方法となります。
#環境
クラウド:GCP
WEBサーバーをVue/CloudRun
APIサーバーをGolang/CloudRun
DBサーバーをMySQL/CloudSQL
#原因
APIを叩くたびにAPIサーバーとDBサーバー間で新しいコネクションができているから
と判明した。
つまり、コネクションの使い回しができていなかった。
#対策
database.sqlの以下のメソッドを使用し、コネクションプールの設定を行う。
また、ORMでもコネクションプールできるらしい。
メソッド名 | 説明 |
---|---|
func (db *DB) SetMaxOpenConns(n int) | 接続の最大数を設定。 nに0以下の値を設定で、接続数無制限。 |
func (db *DB) SetMaxIdleConns(n int) | コネクションプールの最大接続数を設定。 |
func (db *DB) SetConnMaxLifetime(d time.Duration) | 接続の再利用が可能な時間を設定。dに0以下の値を設定で、ずっと再利用可能。 |
以下のようにして実装。
DBconnection
func NewLocalDBConnection() error {
/* ===== connect datebase ===== */
// user
user := os.Getenv("MYSQL_USER")
// password
password := os.Getenv("MYSQL_PASSWORD")
// connection database
database := os.Getenv("MYSQL_DATABASE")
// connection host
host := "localhost"
// connection port
port := "3306"
var err error
DB, err = setupDB("mysql", fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?parseTime=true", user, password, host, port, database))
if err != nil {
return fmt.Errorf("sql.Open: %v", err)
}
return err
}
//this function is a function for connection pooling
func setupDB(Driver string, dsn string) (*sql.DB, error) {
db, err := sql.Open(Driver, dsn)
if err != nil {
return nil, err
}
//コネクションプールの最大接続数を設定。
db.SetMaxIdleConns(100)
//接続の最大数を設定。 nに0以下の値を設定で、接続数は無制限。
db.SetMaxOpenConns(100)
//接続の再利用が可能な時間を設定。dに0以下の値を設定で、ずっと再利用可能。
db.SetConnMaxLifetime(100 * time.Second)
return db, err
}