完璧なHTTPプロトコルパフォーマンス

Webパフォーマンスの1つの側面は、ユーザーが観察できる遅延を減らすことです。 ページをできるだけ早く準備してください。 HTTPプロトコルに関して、これは理想的な通信プロトコルが次のように見えることを意味します。







クライアントは最小量のデータを送信してその要求を記述し、サーバーはページを表示するための最小量のデータを送信します。これはすべて、可能な限り最小限の通信ラウンドで発生します。 サーバーに送信される、またはサーバーから受信される過剰なデータは、ダウンロード時間の増加と、パケット損失、通信チャネルの輻輳の可能性の増加を意味します。 プロトコルの「おしゃべり」と遅延(特に100ミリ秒が最適な応答時間であるモバイルネットワーク)のためにデータを送受信する余分なサイクルも状況を悪化させます。



したがって、理想的なケースを説明した場合、HTTPプロトコルはそれに対応していますか? そして、どうにかしてそれを改善できますか?



HTTP / 1.1

HTTP / 1.1は多くの理由で優れたプロトコルですが、残念ながら、最新のWebアプリケーションの使用方法のため、パフォーマンスはそれらの1つではありません。 そして彼らは今日このように使用しています:







あまり良くない。



クライアントが必要なファイルをダウンロードするためにサーバーに何度もアクセスするため、WebアプリケーションによるHTTP / 1プロトコルの使用はかなりおしゃべりです。 HTMLが最初にロードされ、次にCSSとJavascriptがロードされます。 次の各ファイルをダウンロードして、サーバーとの「会話」に新しい章を追加し、全体的なページ読み込み遅延を増やし、「必要な通信ラウンドを最小限に抑える」という規則に違反します。



さらに、リソース要求自体でさえ、すでに多くの余分なデータを追加しており、「最小限必要なデータ」のルールに違反しています。 これは、リファラー、ユーザーエージェント、そしてもちろん、各リクエストで繰り返されるCookieなどのヘッダーが存在するためです。これらは、必要な最小数(現代のWebの中間ページに必要なリソースの数に応じて)から100倍になることもあります。



そして最後に、 HOLロック現象に固有のHTTP / 1プロトコルにより、いくつかの個別のリソースを1つにまとめるのが一般的な方法になりました(たとえば、 CSS spriting )。 ただし、これらの気の利いたHTTP / 1ハッキングはすべて代償が伴います。 クライアントが特定のページを表示するのに現在必要なデータよりも多くのデータをダウンロードするように強制します。これは、私たちが説明した理想的なケースに違反します。



すべてが述べられているにもかかわらず、HTTP / 1.1はパフォーマンスの面でもそれほど悪くはありません。 たとえば、変更されていないリソースを再ロードする必要がないキャッシング 、およびファイルの新しいバージョンをダウンロードする必要があるかどうかを理解できる条件付きクエリがあります。



HTTP / 2



HTTP / 2プロトコルは、いくつかの方法で1.1の問題を解決しようとします。



  1. 完全多重化とは、HOLロックの問題を解決することです。 1つのHTTP接続を介してページのすべてのリソースをダウンロードできます。リクエストの数を心配する必要はありません。 ファイルを1つに接着する「最適化」は過去に残しておくことができます。
  2. ヘッダー圧縮は冗長性の問題を解決します。 これで、文字通りいくつかのIPパケットで数十(または数百)の要求に対応できます。 これにより、理想的なプロトコルの「最小データセット」に近づくことができます。
  3. HTTP / 2を使用すると、サーバーは、クライアントが要求する前にデータをクライアントに送信できます。 これにより、クライアントとサーバー間の通信のラウンド数が削減されます。




したがって、HTTP / 2プロトコルを使用した通信セッションは次のようになります。







ここでは、クライアントが要求する前に、サーバーがクライアントにCSSとJavascriptの送信を開始する方法を確認できます。 サーバーは、HTMLをリクエストしたクライアントが関連するCSSファイルとJavascriptファイルをリクエストする可能性が高いことを知っています。つまり、リクエスト自体を待たずにそれらを送信できます。 したがって、待機時間を短縮でき、ネットワークをより効率的に使用できます。



これはすべてそれほど単純ではないことに注意してください。 HTTP / 2には、サーバーがクライアントリクエストなしで送信する必要があると判断するタイミングとタイミングに関する未解決の質問がまだあります。



HTTP / 2 +キャッシュダイジェスト

サーバーによって開始されたファイル転送に関する適切な質問は、「クライアントのキャッシュに既にそのコピーがある場合はどうなりますか?」です。 実際、クライアントが既に持っているものをクライアントに強制的に送信するのは愚かなことです。



この場合、HTTP / 2を使用すると、クライアントはRESET_STREAMメッセージを使用してそのようなリソースのダウンロードを時期尚早に完了できます。 しかし、この場合でも、不必要なデータを追いかけ、通信のラウンドを追加しています。これは避けたいと思います。 記事の最初の段落のルールを覚えています。「ページを表示するために必要な最小限のデータのみを転送します。」



この問題に対する提案された解決策は、クライアントにコンパクトなキャッシュダイジェストを作成してサーバーに転送する機会を与えることで、クライアントが絶対に必要としないリソースを知ることです。







キャッシュダイジェストはGolombコードを使用するため、キャッシュにどのリソースがあるかをサーバーに説明するために、ブラウザが必要とする平均ページサイズは1000バイト未満であると想定するのが現実的です。



今では、クライアントとサーバーの通信の不要なサイクル、冗長データの転送、複数のファイルの1つおよび同様のハックへの貼り付け、不要なデータの非効率的な送信を本当に回避しています。 これにより、理想に非常に近づきます!



キャッシュダイジェストは、これまでプロトコルを拡張するための提案にすぎませんが、HTTPコミュニティには多くの関心が寄せられています。 近い将来、それらの使用を確実に確認して評価します。



TCP

ブラウザがページをロードするために使用する他のプロトコルの全体的なパフォーマンスへの影響について話しましょう。 また、重要なこともあります。上記のHTTPの最初のバイトが転送される前でも、TCPは3倍のハンドシェイクを使用します。







これにより、各通信セッションに「おしゃべり」が追加されます。 TCP Fast Openを使用すると、アプリケーションはSYNおよびSYN + ACKパケットでデータを直接送信できます。 残念ながら、これは現在LinuxおよびOSXでのみサポートされており、さらにコミュニティが現在取り組んでいるHTTPプロトコルでTCP Fast Openを使用する機能がいくつかあります。 たとえば、SYNパケットに添付されたデータが一度だけ送信されることは保証されません。 これは、攻撃に使用される可能性のある潜在的な繰り返し要求の脆弱性を開きます。 したがって、POST要求はTCP Fast Openを使用するのに適した候補ではありません。 さらに、いくつかのGETリクエストにも顕著な副作用があり、ブラウザには、そのようなリクエストとそうでないリクエストを区別する手段がありません。



TLS

TLSは、TCP接続が確立された後、クライアントとサーバーの相互作用の別のレイヤーを追加します。 次のようになります。







これらは、HTTPプロトコルが最初の要求を送信する前の2つの完全なメッセージングサイクルです。 おしゃべりでしょ? クライアントとサーバーがすでに通信している場合、通信をわずかに減らすことができます。







すぐに、 TLS 1.3では、クライアントとサーバーが以前に通信したことがある場合に「ゼロ」ハンドシェイクを実現できます。つまり、HTTPプロトコルは、サーバーに送信される最初のデータパケットにペイロードを追加できます。 ただし、TCP Fast Openの場合と同様に、リクエストの重複を避けるためのソリューションが必要です。



HTTP /次

TCP Fast OpenおよびTLS 1.3は、接続を開くときのクライアント/サーバー通信サイクルの数を減らします。 同じことを達成する別の方法は、以前に開いた接続を再利用することです。 HTTP / 2接続をより積極的に組み合わせる方法についての議論があります。 これにより、新しい接続を開くコストを回避できるだけでなく、既存の接続をより効率的に使用できるようになります。TCPは、長寿命で密度の高いデータ接続に最適なプロトコルです。 これには、接続を安全に再利用して他のソースと連携できることを証明する証明書をクライアントに送信することが含まれます。



さらに多くの基本的な実験が議論されています: QUICのようにTCPをUDPに置き換えます。 多くの物議を醸す問題がありますが、最初のデータ交換を実質的にゼロに減らす見込みは非常に魅力的です。 さらに、送信されたときに間違った順序でデータにアクセスする機能も非常に便利です。 これは、TCP(順序付きパケット配信を使用するプロトコル)でHOLロックを回避する別の方法です。 必要なパッケージを選択し、一部が失われたことを理解し、それらを再度リクエストします-リクエストの繰り返しの結果を待たずに次のパッケージの処理を続けます。



QUICはまだ始まったばかりであるため、しばらくの間は適切な実装は行われません(おそらくまったく行われません)。 可能なオプションの1つは、QUICを例として使用してアプローチのすべての長所と短所を調べ、Webアーキテクチャのこのような劇的な変更にぶつかることなくTCPパフォーマンスを改善する方法を理解することです。



All Articles