『WEB+DB PRESS Vol.95』読書ノート

2017/01/03

WEB+DB PRESS Vol.95』を読んだので、学んだ点をまとめる。

特集3 試して学ぶHTTP

ヘッダ

キャッシュ

Cache-Controlヘッダ

キャッシュの可否とキャッシュの利用期限(いつまで保持するか)を指定できる。

Expiresヘッダ

Cache-Controlヘッダと併用する。
キャッシュの利用期限を指定するのがCache-Controlなのに対して、キャッシュのコンテンツの有効期限がいつまでかを指定する。
すなわち、Cache-Controlでの指定方法とExpiresでの指定方法の違いは次のようになる。

If-Modified-SinceヘッダとIf-None-Matchヘッダ

クライアントからキャッシュの有効期限内かあるいはキャッシュが正しいかを確認するために送るヘッダ。

キャッシュの利用

キャッシュの利用方法は次の二つ。

  • クライアントが持っているキャッシュを最初から信頼し、サーバにリクエストを送らない。
  • If-Modified-Sinceヘッダ等を付けてサーバにリクエストしたときに、クライアントがキャッシュをすでに持っているとしてリソースを返却しない。

実際にキャッシュを利用するか、どれくらい利用するか、If-Modified-Sinceで問い合わせるか等の違いは全てクライアント実装次第。
指定日時までキャッシュしてほしければCache-ControlとExpiresを適切に指定する。
キャッシュしてほしくない場合は、Cache-Control: no cacheを指定する。

Hostヘッダ

最小限のHTTP通信では、サーバにはどのドメイン名でユーザがアクセスしたかを知る方法がない。
これを知るにはクライアントがHostヘッダにドメイン名を指定する。ブラウザを利用していれば、アドレスバーに入力したURLのホスト部が入る。

Accept-Languageヘッダ

クライアントが期待する言語を指示する。このヘッダによって表示内容を切り替えられるようにするとよい。

コネクション

Connectionヘッダ

HTTP/1.1ではデフォルトの挙動がKeep-Alive。
次の場合はコネクションを使いまわさない。

  • Connection: closeを指定する。
  • Content-LengthかTransfer-Encoding: chunkedが存在しない。
Transfer-Encoding: chunked

Transfer-Encoding: chunkedはレスポンスの長さがわからない時に、データを細切れにして送るためのヘッダ。動的にデータを送信する場合、例えば動画のライブ配信のようなデータの場合に使う。

HTTP/2

HTTP/1.1の問題点

  • ヘッダが圧縮できない。
  • リクエスト間で重複した内容のヘッダを何度も送信してしまう。
  • リクエストを多重化できない。

最後の多重化について、HTTP/1.1では、1つのTCPコネクションに対して、基本的にリクエストとレスポンスを1組ずつしか送受信できない。
クライアントがレスポンスを受信するまでの間、クライアントは何のデータも受信できず、この時間—RTT(Round-Trip Time)—は回線を使えない時間となってしまう。
そして、通信時間はホスト間の物理的な距離にも影響を受けてしまうため、大陸間通信では特にボトルネックになる。

ストリーム多重化

HTTP/2では、リクエストとレスポンスのペアをストリームと呼ぶ。
単一のTCP/TLSコネクション上に独自のセッション層を構築し、各セッションで同時にストリームを開始できるようにして、多重化を実現する。
リクエストのたびに発生するRTTがボトルネックになっていたが、並行リクエストができることで、あるセッションのRTTで他のセッションのリクエストを開始することが可能になった。

HPACK

ヘッダを圧縮して送信する仕様。静的ハフマン符号化による文字列の圧縮と、インデックス符号化によって構成されている。
User-Agentのような全てのリクエストで同じ文字列を送信することになるヘッダは、インデックス化によってヘッダそのものではなくインデックス値のみを送信するれ場良いことになり、データ量が大きく削減できる。

フロー制御

HTMLを取得した後に、CSS、JavaScript、画像等の必要なアセットを取得するときに、順番をコントロールする必要がある。順番がコントロールできないと、画像を先に取得しようとして回線が占有され、ページのレンダリングが開始できない事態に陥りかねない。

各ストリームには依存関係を設定できる。
依存先アセットが先行してダウンロードを完了させられる。

また、各ストリームには帯域利用の分配率を重み付けとして設定できる。
分配率は1~256の整数で指定し、各ストリームで100%を分配率によって分散する。

QUIC

HTTP/2によりHTTPの性能は向上するが、TCP/IPプロトコルが次のボトルネックになる。UDPでは通信の信頼性が担保できないので、GoogleがUDP上に独自の信頼性向上機能を追加したQUICを開発している。

AWS LambdaとServerles Frameworkでサーバレスアーキテクチャ

サーバレスアーキテクチャ

Webサーバやアプリケーションサーバのような常駐プロセスがない。

Webアプリでは、CGIプログラムに代表されるリクエストが来たらプロセスをforkして実行するものから、サーバプロセスとして常駐するアーキテクチャへの変遷してきた。fork型はメモリリークや他プロセスへの悪影響を心配しなくていいシンプルで安全なアーキテクチャだが、forkのコストが高かった。
サーバレスアーキテクチャは起動時のオーバーヘッドが少ないコンテナを実行環境にすることで、fork型のように、リクエストごとにプログラムの起動と終了を行う。

メリット

サーバプロセスはメモリ上に常駐し、状態を持つ。その状態を複数のタスクが共有する。対して、サーバレスアーキテクチャはShared Nothingであり、負荷分散が容易となる。セッションをどうするかなどを考慮する必要がない。プログラムに障害があった場合も他のタスクに影響を与えにくい。

データ処理の高速化

MySQLクエリチューニング

  • カバリングインデックス
  • UNIONの活用(1クエリ1インデックスの制限を超えるためにOR条件をUNIONに変換する。OR条件以外の制限回避方法だとサブクエリ化やJOIN化など)
  • ORDER BY狙いのキー(+LIMIT句。ORDER BY狙いのキーはMySQLのオプティマイザでは選択されないことが多く、クエリにFORCE INDEXを付けることを考える)

スワップ

vm.swappinessを1などの小さい数字にして、スワップを抑制する。ここでvm.swappinessに0を設定してはいけない。
Deploying Oracle Database 12c on Red Hat Enterprise Linux 6 Best Practicesに以下の通り記載があるように、Red Hat Enterprise Linux 6.4以降はswappinessの定義が変わっている。

Starting with Red Hat Enterprise Linux 6.4 and above, the definition of swappiness has changed. Swappiness is defined as a value from 0 to 100 which controls the degree to which the system favors anonymous memory or the page cache. A high value improves file-system performance, while aggressively swapping less active processes out of memory. A low value avoids swapping processes out of memory, which usually decreases latency, at the cost of I/O performance. The default value is 60. Warning: Since Red Hat Enterprise Linux 6.4, setting swappiness to 0 will even more aggressively avoid swapping out, which increases the risk of out-of-memory (OOM) killing under strong memory and I/O pressure. To achieve the same behavior of swappiness as previous versions of Red Hat Enterprise Linux 6.4 in which the recommendation was to set swappiness to 0, set swappiness to the value of 1. The recommendation of swappiness for Red Hat Enterprise Linux 6.4 or higher running Oracle databases is now the value of 1.

vm.swappinessを0にしてしまうと、OOM Killerのリスクが高くなる。

setting swappiness to 0 will even more aggressively avoid swapping out, which increases the risk of out-of-memory (OOM) killing

クエリキャッシュ

MySQLでは更新クエリが発行されると、該当するテーブルを参照しているキャッシュがすべて削除される。さらにこのとき、参照と更新にロックがかかってしまう。
更新の多いテーブルでSQLチューニングが進んでいる環境では、query_cache_size=0にしてクエリキャッシュを無効にすべき。一部の時間のかかるクエリをキャッシュしたい場合はアプリケーション側でキャッシュする。

Javaの新定石

JUnit

Hamcrestの問題点

IDEでstaticインポートすると使用できないメソッドも選択できてしまう。また他にstaticインポートしているライブラリを同時に使用すると、メソッド名の競合が起きる。

AssertJ

流れるようなインタフェースを使用したHamcrestに代わるアサーションAPI。assertThat()はstaticインポートするものの、startWith()等の検証メソッドはassertThatのメソッドとなっており、staticインポートしていないため、IDEで書きやすい。

-読書ノート