最近は登壇とかでエネルギーを取られて、砂場活動シリーズ(?)全然できていませんでした。せっかく前期に砂場を作ったので、勉強の場にしていきます。現状のボトルネックがどこにあって、どこを改善していきましょう、というループを回します。ISUCONとかやってる人には当たり前のことばかりだと思うけど、その辺あまり慣れていないのでぼちぼちとやっていきます。派手なことななく地味にやっていく。
現状を知る
改善をするためには現状のパフォーマンスを知ることが重要です。趣味サイトはユーザーが自分しかいないので、ベンチマークスクリプトをかけてパフォーマンスを見ていきます。スプレッドシートにまとめていくのは面倒だったので、Mackerelのプラグインを書いて可視化しました。
改善していく中でRDS/ElastiCacheのCPU/メモリ/コネクション数/トラフィック量などが一目で分かるようなダッシュボードも作りました。結果ではなく原因になった場所がどこかを調べるのに便利。
数値だけ見ても分からないことも多いので、CloudWatch LogsにアプリやNginxのログを流すように設定。
あれこれ改善
自分しか使っていないとアホなことをやっていても問題にならないけど、ベンチマークを回すとそういったところが問題点になってくるので改善していく。
- fullscanが走っているところにDBにインデックスを張る
EXPLAIN ANALYZE
とかやりながら効果を見ていく。あんまり見方を知らなかった...- https://github.com/syou6162/go-active-learning/pull/32
- コネクションプールを使い回す
- 自分しか使っていなかったのでリクエストの度にコネクション作ってたけど、リクエスト数増えるとまあまずいよね
- poolsizeをどれくらいにするといいか感覚があんまりない...
- https://github.com/syou6162/go-active-learning/pull/29
- https://github.com/syou6162/go-active-learning/pull/33
- N+1を潰す
- 潰しましょう
- Redisのパイプラインを使う
- 1つずつコマンドを送るのではなくまとめてやれる方法
- 必要なフィールドのみ取得するようにする
- 特徴量やhtmlもredisに雑に放り込んで学習時には使っていたけど、apiのレスポンスを返すときには使っていない(
SELECT *
的なことになっていた) - 結構巨大なフィールドなので、不必要なものは削って必要なものだけ返すようにする
- jsonとしてredisのvalueに放り込んでたけど、取ってくるフィールドを選択できるようにハッシュ型に変更した
- https://github.com/syou6162/go-active-learning/pull/31
- 特徴量やhtmlもredisに雑に放り込んで学習時には使っていたけど、apiのレスポンスを返すときには使っていない(
- アプリケーションサーバーやDBのリソースは余ってるけど、レイテンシーが悪化するようになってきた
- ちょっと悩んでしまったけど、負荷試験をされる側ではなくて負荷試験をする側のネットワーク帯域がボトルネックになっていた
- 負荷試験を複数のインスタンス(Fargate)から実行するようにして負荷分散
- goroutineで
too many open files
- ありがちだけどミスったコードを書いてパフォーマンス出なくなってた
- Golang parallelism issues causing “too many open files” error | The Technical Blog of James
- nginxで
Too many open files
- 何やねんと思ったけど、ファイルディスクリプタの上限に引っかかってしまっていた
- Fargateで動かしている場合も変更できるので増やした
次回
この辺までやるとあとはFargateの数増やしたり、ElastiCache/RDSのスペックを上げたり、リードレプリカの台数を増やせば捌けるリクエスト数も増やしていけそうなかという目処が立ってきた。次回作にご期待ください。
負荷試験をしていたら順調にAWSへの課金額も伸びてきた😇。
理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)
- 作者: 奥野幹也
- 出版社/メーカー: 技術評論社
- 発売日: 2015/03/10
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (20件) を見る