Web技術勉強会
Webパフォーマンス改善編
田実 誠
今回は一般的かつ超絶基本的なWeb/DBサーバ
のパフォーマンスチューニングに関するお話をします。
※C10Kとかマルチスレッドとかの話はしません
• Webサーバのパフォーマンス改善
• 基本的なHTMLの評価順序
• TCP Connection
• Keep-Alive
• CDN(RTT/キャッシュ)
• ブラウザのキャッシュ
• ドメインシャーディング
• 圧縮
• gzip
• minify/concat
• 非同期処理
• キューイング
• DBのパフォーマンス改善
• Index
• バッファキャッシュ
• NoSQL
アジェンダ
基本的なHTMLの評価順序
• ドキュメント(HTML)のロード
• DNS、TCP 3way、TLS、TCP
• HTMLのレンダリング
• JS, CSS, 画像ファイルのダウンロード
• DNS、TCP 3way、TLS、TCP
• JSの評価
Keep-Alive
• TCP 3way handshakeは時間のオーバーヘッドがあり効率的ではない
→TCP 3way handshakeを省略したい
• Keep-Aliveは一つのTCP接続を使い回す仕組み
→HTTPヘッダにConnection: Keep-Aliveを指定することでWebブラウザ側がTCP接続を使いま
わしてくれる
• HerokuはデフォルトでKeep-Aliveしてくれるっぽい(ブラウザ – Heroku Router間?)
HTTPリクエスト(HTMLくださーい)
HTTPレスポンス(HTML渡しまーす)
SYN(これから通信するよー)
SYN/ACK(OKよろしくー)
ACK(じゃあ次のリクエストで送るよー)
リクエスト/レスポンスの前段で200ms
Keep-Alive
• オレンジ=>TCP 3way handshake
• 緑=>TTFB(Time To First Byte):HTTPリクエストからレスポンスのfirst byteまでの時間
• 青=>ダウンロード時間
• 灰色=>待機時間
• 紫=>TLS handshake
• 緑+青=>HTTPリクエスト~HTTPレスポンスを全て受け取るまでの時間
Keep-Alive
2回目以降はTCP接続を使い回すようになっている
ちなみにTLSありだと…
• TLS/SSLハンドシェイク分のオーバーヘッドがかかるが、こちらも使い回しの概念が有る
CDNによる改善
• Contents Delivery Network
→静的コンテンツを返すためのサーバ
• Akamai、Cloud Front(AWS)、cloud flare
• 負荷分散(静的コンテンツはCDN、動的コンテンツはアプリサーバ)
• クライアントから一番近いエッジサーバ(配信サーバ)からファイルを取得
→レイテンシ(RTT)の改善
• CDNが各リソース(静的ファイル)をキャッシュするので高速なレスポンスを実現
→アプリケーションサーバが静的ファイルを返すよりかは効率的
Client CDN Webサーバ
キャッシュ切れの時だけ
リクエスト
静的ファイル
リクエスト
レスポンス(CDNのキャッシュ)
CDNのエッジサーバに対するアクセス
出典:http://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-amazon-cloudfront
ブラウザキャッシュによる改善
• HTTPのキャッシュ機構を利用して、ブラウザ自体にHTTPレスポンスをキャッシュし、レスポンスを使い
回す→これを使って静的ファイルのロード短縮が可能
• Cache-Control、Expiresヘッダを使ってブラウザにキャッシュの有効期限を伝達
キャッシュを利用しているので
Heavy.js(1.7MB)のロード時間が短縮される
ドメインシャーディングによる改善
• ブラウザの同一ドメインに対するHTTP同時接続数は6つまで
• ドメインを分けてリクエストすればMAX同時接続数をドメイン数×6まで伸ばせる
同時!
圧縮(gzip)
圧縮前
圧縮後(1.7MB=>12.3KBに圧縮)
圧縮(minify/concat)
• JavaScriptのソースコードをminifyすることでファイルを小さくできる
→構文上削除しても問題ない改行や空白の削除、変数名を短くしたり
• 複数のJavaScriptを読みこませる場合は、読み込ませる順番にJavaScriptを連結すればクライア
ント側は一つのJavaScriptをダウンロードすれば良いのでTCP接続としては効率的
• webpackは画像ファイルもBase64形式でJSファイルに取り込む
• AngularのminifyタスクではテンプレートのHTMLファイルでさえJSファイルにする。そのHTML
ファイルの内容も改行等の無駄な文字列を削除したり…
• CSSスプライトもTCP接続数削減の一つ
重い処理は非同期に
• 画像処理等の重い処理は非同期にして他のサーバ(ワーカ)に処理を回す
• Herokuでは1リクエスト30秒ルールがあるので、重い処理はワーカー等を使った非同期処理に回す
※Herokuに限らず同期処理で30秒待たされるのはUX的にNGな感じだと思うので一般的な話とし
て…
• SQS(AWS)、RabbitMQ(AMQP)、Redis(Resqueとか併用して)
workerQueue
Enqueue Dequeue
Client
HTTP/2
• TCP接続の多重化(一つのTCP接続で複数のリクエストを同時に実行できる)
→アセットの結合がいらなくなる?
• バイナリープロトコル(HTTP/1.1はテキストプロトコル)
• ヘッダ圧縮
• 優先度制御
• サーバプッシュ
リクエスト1
レスポンス1
リクエスト2
リクエスト2
リクエスト3
リクエスト3
DBパフォーマンス改善
• Indexを効かせるSQL(EXPLAINを見る)
• 効率的なSQL(INとかJOINを使って、できるだけまとめて取得する)
• O/Rマッパだと良くも悪くもSQLが隠蔽されてしまうのでパフォーマンスの悪い箇所はSQL文をデバッグして確かめる
• コネクションプール(TCP 3way handshakeと接続処理の省略)
• メモリ系のDB設定値の調整
• ファイルキャッシュ(メモリに載せよう)※後述
• メモリが足りなければスケールアップ(メモリ増設)を検討
• JOINでコストがかかるクエリは予めJOINさせる
• 全文検索はElasticSearch等の全文検索エンジンを使う
• 利用できればNoSQLと併用
• MemcachedやRedisなどのインメモリ系KVSはアプリキャッシュとして有用
• シャーディング/テーブル分割/非正規化
Linuxファイルキャッシュ(ページキャッシュ)
• Linuxには開いたファイルの内容を自動的にキャッシュする機構がある
• RDBのレコード読み込みも結局のところファイル読み込みなので、DBのファイルがメモリに乗ればインメモリDBっぽ
く処理される(とはいえNoSQLのインメモリDBは色々と最適化されているので性能差は大きい)
SELECT * FROM performance_test WHERE int_field = 10000000;
ページキャッシュ HDD SSD
× 27674.021 ms 13330.887 ms
○ 4516.920 ms 4642.373 ms
メモリに載ってしまえば、ディ
スクは関係ない
クエリによるが3~4倍くらいの差
HDDとSSDの速度差は
2倍くらい?
どうやってボトルネックを探すか?
• Chrome Developer Tool
• クライアントから見たパフォーマンス/挙動を確認可能
• HTTPのRTT、ファイルサイズ、TCP接続数
• NewRelic
• アプリに特定のコードを仕込むことでアプリケーションサイドのパフォーマンスを確認可能
• CPUを使いまくって遅い(画像処理等)のであれば非同期化
• I/O系が遅いのであれば…
• DB→SQLのチューニング or インメモリなNoSQLを使うとか
• Webサービス→非同期化
• 各RDBのEXPLAIN
• Indexが効くSQLに
• DBの設定
• RTTの壁は超えれないので何とか工夫する
• TCP接続の特性を理解して正しいチューニングをしましょう
• Keep-alive
• ドメインシャーディング
• CDN
• キャッシュ
• 圧縮(gzip, minify)
• 重い処理は非同期で。ワーカーに回して負荷分散。
• HTTP/2が色々と解決してくれるかも
• DBは基本的なSQLのチューニングとインメモリKVSによるアプリキャッシュ等で工夫する
まとめ
• ブラウザのキャッシュコントロールについて
http://qiita.com/hkusu/items/d40aa8a70bacd2015dfa
• Heroku Router
https://devcenter.heroku.com/articles/http-routing
• 書籍
• ハイパフォーマンス ブラウザネットワーキング ―ネットワークアプリケーションのためのパフォーマンス最適化
• SQL実践入門──高速でわかりやすいクエリの書き方 (WEB+DB PRESS plus)
• 内部構造から学ぶPostgreSQL 設計・運用計画の鉄則 (Software Design plus)
• ウェブパフォーマンスの基礎とこれから
http://www.slideshare.net/kawada_hiroshi/ss-46149727
• HTTP/2
http://www.slideshare.net/kazuho/http2-51888328
http://www.slideshare.net/asumaslv/http2-57141644
• ファイルキャッシュ
http://d.hatena.ne.jp/naoya/20070521/1179754203
• コネクションプール
http://blog.yuuk.io/entry/architecture-of-database-connection
参考URL

第2回Web技術勉強会 webパフォーマンス改善編