こんちは、開発2部の吉岡です。
負荷テストについての続き的なエントリーです。
負荷を考慮しながら開発を進めていきますが、負荷テストでビミョウな結果が出てしまったなら…
確認点をちょっとまとめて見ました。
負荷対策という意味では、もっと色々な方法があるかと思いますが、負荷テスト後にチェックするなら、、という感じです。
ボトルネックの調査
まずはどこがボトルネックになって、パフォーマンスが上がっていないか調査します。
ログから調査する
- 各種ミドルウェアのエラーログ
エラー時にエラーメッセージやスタックトレースをロギングすると追跡しやすいです。
負荷テスト時には、コネクション数の上限到達やタイムアウトなどのエラーが発生している場合があります。
- 各種ミドルウェアのアクセスログ
処理時間を出力しておくとボトルネックとなっているリクエストを特定しやすいです。
複数のサーバに分散していると手間なので、fluentd(td-agent)で集積してmongoDBあたりに突っ込んでおくと、確認作業もかなり楽になります。
リソースの確認
各サーバーのCPUや、メモリ、I/O、swap、ネットワーク負荷などを確認しておきます。
マルチコア対応のミドルウェアでは、上手く各コアに分散出来ているか確認します。
PHPのプロファイリング
WinCacheGrindを使ってボトルネックになりそうな箇所を調査してみます。
単純なループ処理でも、高負荷の状態ではボトルネックになることがあるので、実装方法などを検討してみます。
ボトルネックが発見された時の対策
SQLやDB処理に問題がある
- indexの効かないSQLは実行しない。
explainしてみて、typeがALLやindexになっているものはアウトです。
indexが使いにくい場合(検索項目が可変、0、1のフラグなど)、KVSの利用や、仕様の調整等を検討してみます。 - ループ処理内でのSQL発行
ループ中でINSERTを発行している場合は、バルクインサートを使用するように変更します。
- 排他制御
排他制御が必要な項目と不要な項目が同一テーブルに混在する場合は、テーブルの分割を検討します。
- ディスクI/Oの負荷に問題がある。
sync_binlogが必要かどうかで変わってくるかと思うのですが…
ストレージをSSDやioDriveに出来ないか検討してみます。
使用しているクラウドサービスに高速ディスクオプションがある場合は、こちらも検討してみます。
また、テーブルを垂直分散/水平分散することで負荷対応出来ないかも検討します。
Webサーバー、PHPの処理に問題がある
- メモリの設定
PHPのmemory_get_usage()をロギングするなどして、メモリを大量に使用する処理を特定し、処理の分割を検討します。
オンラインではあまりありませんが、ランキング集計など大量データを扱うバッチ処理等で使用メモリの設定が問題になっている場合があります。
- Webサーバーの接続数に問題がある
最大接続数を再検討してみます。スペック的に限界であれば、スケールアウトを検討します。
開発時点から気を付けること
開発時から、log-queries-not-using-indexes=1にしてindexが効いていなクエリを洗い出しておきます。
あとは、負荷がヤバそうな仕様は、プランナーとちゃんと話をしておくことでしょうか…
jenkinsで軽い負荷テストを継続的に行うようにしても面白いかもしれません。