App Service(Microsoft Azure)とAzure SQL DatabaseのReconfiguration対応
概要
- Azure環境でシステム開発している中で、Reconfigurationという現象に遭遇したので、その時の対応についてまとめる
Reconfigurationについて
- Azure SQL Databaseには、サービスの仕様としてReconfigurationというものがある
- Reconfigurationが発生すると、数秒〜数十秒の間、DB接続ができなくなる
- Reconfigurationは、不定期で発生する(現状だと1ヶ月に2、3度)
- Reconfigurationそのものは、安定したDBの稼働のために必要なものらしい
- Azure SQL Databaseを使用するには、Reconfigurationが発生することを前提で開発する必要がある
[SQL Database] Reconfiguration (リコンフィグレーション) は悪ではない。 – Microsoft SQL Server Japan Support Team Blog
環境
本番環境
- Azure App Service(Windowsサーバ)
- PHP5.6
- Lumen
- Azure SQL Database(SQL Server)
開発環境
- vagrant(CentOS)
- PHP5.6
- Lumen
- Azure SQL Database(SQL Server)
Microsoftの公式ドキュメントの対処方法
- Microsoftの公式ドキュメントでは、Reconfgiuration発生を検知し、wait後にリトライを実装する流れを推奨。
- Reconfiguration発生時に使用した接続は使用できないため、改めて接続し直す必要がある。
テスト方法
- 基本的には、Reconfigurationは不定期に発生するが、意図的に発生させることも可能。
- Azure SQL Databaseのプランを変更することで、プランが切り替わる間の数秒間だけReconfigurationが発生。
- Azure Portal上からプラン変更して、SQL実行を連続して実行することでテスト可能。
ハマるポイント
Reconfigurationの判断
- 本番でDB接続エラーが発生したときに、それがReconfigurationによるものなのかは現在MSサポートに問い合わせる必要がある。 以前までは、sys_event.logに出力されていたらしいが、現在は出力されない。
- Microsoft公式ドキュメントでは、Reconfiguration発生の判断をSQLのERRCODEで制御する方法を記載しているが、コネクションプーリングが有効になっていると古いコネクションを使用することでERRCODEに値が入らないことがある、そのときには、SQLSTATEしか入っていないため、そちらで判断する。(これはPHP以外の言語では大丈夫かも。ドライバの問題な気がする。)
リトライ処理をしても同様の接続エラーが発生
- Lumenでは、リクエスト単位でPDOをキャッシュする機構がある
- Lumenの機構を改修して、Recofiguration発生時にのみ、PDOを再生成して失敗したSQL実行という流れを単純に作って対応したが、 Reconfiguration発生時と同様の接続エラーが発生
- PDOを再生成しても内部ではReconfiguration発生時のプールを使用しているため、エラーが発生する
App Serviceのコネクションプーリングの制御
- App Serviceのプラン(サーバスペック)によって、プールの最大数などが決まる仕様になっている
- PHPからプールを破棄するAPIなどは用意されていない
- PHPからアクティブなプール数を取得するAPIなどは用意されていない
- コネクションプーリングを無効化すると、その都度確実に接続しにいくため、エラーが発生し続けることはない
- 但し、遅くなる。
最終的な対応方法
- 基本方針として、コネクションプーリングを一律無効化するのは、パフォーマンスの観点からNGなため、デフォルトはプールを有効化
- 現状は対応1でも問題なく動いているため、様子見。これでも駄目な場合、別途キューのプロセス管理が必要になるが、対応2を検討
対応1
- Reconfigurationを検知したときに、wait後、コネクションプーリングを無効化したPDOを生成し失敗時のSQLを再実行
対応2
- Reconfigurationを検知したときに、システム全体でコネクションプールを無効化するように制御(PDO生成周りの処理改修)
- キューに90秒後コネクションプールを有効化する処理を追加(プールの生存期間が60秒なため、若干の余裕を持たせる)