HTTPの通信を辞書で圧縮する提案について

現在 ChromeではHTTPの通信をBrotliの辞書で圧縮する『Feature: Compression dictionary transport with Shared Brotli』という仕組みの開発が進められています。

この仕組は、来週開催されるIETF 116のサイドミーティングでも議論が行われる予定になっています。

なので、軽くその仕組について予習をしておく。仕組みについて説明したドキュメントはこれ
github.com

Compression dictionary transport

基本的なアイデアとしては、サーバからBrotliの辞書データを提供して、以降のHTTP通信では(使える場合は)その辞書を活用してHTTPレスポンスを圧縮する (辞書データは他のサイトとは共有されない。Pathに合わせて複数の辞書を使い分けできるようになっている)

辞書データとしては、大きく2種類のユースケースがある (圧縮/解凍の利用のながれは一緒)

  • 普通にダウンロードしたJSファイルやCSSファイルをそのまま次回以降の辞書データとして活用する (jsやcssの一部変更があった場合に、ダウンロードし直す際に大きな圧縮効果を発揮する)
  • Linkタグで辞書データを指示し、使わせる

辞書データとしての保持

ファイルを取得する際に、取得したリソースを今後辞書データとして保持するまでの流れを説明します。
今回は、example.comのページからstatic.example.comのjsファイルを取得する流れで説明します。


  • クライアントは、このCompression dictionary transportに対応している場合、Accept-Encodingにsbrを追加してリクエストを送ります
  • サーバは
    • bikeshed-use-as-dictionaryとしてこの辞書を適応するPathの範囲を通知します (ヘッダ名は仮置きとなっている)
    • このやり取りではCORSが必須になるため、Access-Control-Allow-Originを付けます
    • Varyでこのキャッシュキーとして辞書データが依存することを通知する
  • クライアントは、レスポンスを受け取ったらこのデータを辞書データとして保持する

Linkタグで辞書データを読み込むときも概ね同じ流れになります。

辞書データの活用

次に、先の例で保持した辞書データを活用する流れを説明します。

  • クライアントは、辞書データを適応するPathに適合するリクエストを送る際、辞書を持っていることをsec-bikeshed-available-dictionaryヘッダで通知します。
  • サーバは、クライアントが持つ辞書を使って圧縮できる場合は圧縮します。このときヘッダに「Content-Encoding: sbr」が付きます (該当の辞書データがない場合は普通に圧縮する)。

圧縮効果やセキュリティなど

圧縮効果についてリサーチが進められています。
https://github.com/yoavweiss/compression-dictionary-transport/blob/main/examples.md
各サイトのJSファイルなどが大きく圧縮できる事がシミュレートされています。

また、セキュリティについてもCRIMEやBREACHといった圧縮効率から機密データを推測する攻撃が頭をよぎります。そのため、ユーザ固有の機密データが辞書データに含まれないようにしなければなりません。
https://github.com/yoavweiss/compression-dictionary-transport#risks

キャッシュを補助する HTTP Availability Hints の仕様

HTTP Availability Hints」という提案仕様がMark Nottinghamによって提出されています。

この提案仕様では、キャッシュで使用されるVaryを補助します。この情報により、キャッシュサーバは効率が向上します。

背景

例えば


  1. Client 1から英語(en)のコンテンツが要求され、CDNは英語コンテンツをキャッシュする
  2. Client 2から日本語(ja)のコンテンツが要求される

CDNがOriginからレスポンスを受け取った際に、"vary: Accept-Encoding" がついています。そのため、CDNはオリジンのコンテンツがaccept-languageに依存していると判断して、日本語(ja)の要求をOriginにプロキシします。

このとき、Originが日本語(ja)には対応しておらず結局英語(en)のコンテンツが返ってくることもあります。CDNは英語(en)のキャッシュが会ったため、無駄なやり取りをしてしまったことになります。

このケースにおいては、Originがjaのコンテンツを提供できないことをCDNが知っていれば、キャッシュしている英語(en)をClient2に返すことができます。

HTTP Availability Hints

HTTP Availability Hints」では、Varyで指定されたヘッダのうちオリジンが提供可能な種類を示せるようにします

Vary: Accept-Encoding, Accept-Language, ECT
Avail-Encoding: gzip, br
Avail-Language: fr, en;d
Avail-ECT: (slow-2g 2g 3g), (4g);d

Avail-Languageでは、フランス語(fr), 英語(en)が提供であることを示しています。デフォルトとして英語(en)が指定されているので、日本語のコンテンツが来たとしても英語のコンテンツを返していいことがわかります。

現在の提案仕様では、例として次の補足情報が定義されています。

Avail-Encoding
Vary: Accept-Encoding
Avail-Encoding: gzip, br
Avail-Format
Vary: Accept
Avail-Format: image/png, image/gif;d
Avail-Language
Vary: Accept-Language
Avail-Language: en-uk, en-us;d, fr, de

Cookieでは依存するクッキー名を指定できます

Vary: Cookie
Cookie-Indices: id, sid

HTTPヘッダに構造を与えるStructured Field ValuesにDateが追加される

HTTPヘッダの値に、リストや辞書といったデータ構造を定義する『RFC8941 Structured Field Values for HTTP』という仕様があります。
(ヘッダと書きましたが、フィールドという用語た正しいので仕様上はStructured Field Valuesという名称になってます)

これに新しく、Date値を追加する議論が行われています

RFC8941 Structured Field Values

すでに出版されているStructured Field Valuesでは、ヘッダの値として次の値を定義しています。

  • List
  • Dictionary
  • Item
  • Integer
  • Decimal
  • String
  • Token
  • Byte Sequence
  • Boolean


例えば、Dictionaryであれば次のような構造です。

Example-Dict: rating=1.5, feelings=(joy sadness)

IETFで新しいHTTPヘッダを策定する際にこのStructured Field Valuesの仕様に則って定義すれば、シンタックスも曖昧性が無く、パーサーも再利用できるようになります (*すでに定義された全てのヘッダがこのルールでパースできるとは限りません)。

sfbis

RFC8941 の改訂版として "draft-ietf-httpbis-sfbis-01" が現在議論されています。この提案仕様は、新しくDate値が追加されています。

日付を表すHTTPヘッダは多くありますが、文字列で日付を示すよりUNIXタイムで示せるようにしたいという要望も出ておりました。それに答える形になっています。

Date値は次のように@で始まります。

Example-Date: @1659578233

Document Picture-in-Picture が便利

ピクチャーインピクチャー (PIP)

ピクチャーインピクチャー (PIP)は、ブラウザ上で小窓で動画視聴できる仕組みです。

例えば、YouTube上で右クリックして、『ピクチャー イン ピクチャー』を選択すると

次のように小窓で動画を再生してくれます。

他のタブを表示したり、ウィンドウを最小化しても再生され続けるため、作業しながらの視聴時に大変助かります。

Document Picture-in-Picture

現在の『ピクチャー イン ピクチャー』はHTMLVideoElementでしか行なえません。そのためYouTubeのプレイヤー操作(シークバー操作やショートカットキーによる早送り/巻き戻し)は出来ません。

現在 任意のHTMLElements を『ピクチャー イン ピクチャー』可能にする「Document Picture-in-Picture Explained」の議論がされいます。

Chrome Canaryですでに動くので試します。

YouTubeで動画を再生しながら、次のスクリプトデベロッパーツールから実行します。

  const player = document.querySelector("#player");
    const pipOptions = {
    initialAspectRatio: player.clientWidth / player.clientHeight,
    copyStyleSheets: true,
  };
  pipWindow = await documentPictureInPicture.requestWindow(pipOptions);
  const playerContainer = document.querySelector("#player");
  playerContainer.classList.add("pip-mode");
  pipWindow.document.body.append(player);

プレーヤーが『ピクチャー イン ピクチャー』できた (スクショは、タブは切り替えた様子)

セキュリティ関連のHTTPヘッダを一括指定する Baseline ヘッダ

現在のWebでは、セキュリティ上レスポンスヘッダで色々なものを指定します。Webデベロッパーは個別に指定しなければなりません。

そこで、セキュリティ関連のヘッダを推奨デフォルト値に設定できるようにする「Baseline ヘッダ (Opt-into Better Defaults)」が、GoogleのMike West氏によって提案されています。

まだたたき台であり、これからW3CのWebAppSec WGで議論されている予定になっています。

Baseline ヘッダ

次のようにレスポンスヘッダを指定します。

Baseline: Security=2022

これは、次のヘッダを送信するのと同様です。

Content-Security-Policy: script-src 'self';
                         object-src 'none';
                         base-uri 'none';
                         require-trusted-types-for 'script';
                         trusted-types 'none';
Cross-Origin-Embedder-Policy: credentialless
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Resource-Policy: same-origin
Permissions-Policy: /* TBD; some reasonable baseline configuration */
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN

各種セキュリティ関連のヘッダを指定し、XSSを防ぎ、クロスオリジンからの読み込みなどを制限します。

各ヘッダは個別に上書きすることが出来ます。

ブラウザからPCの負荷状況を取得する Compute Pressure API

PCの負荷状況に合わせて、Webサイトでの処理を軽量なものに切り替えたい場合があります。

それを可能にする仕組みである「Compute Pressure API 」がChromeで実装が進められています。なお、仕様の方もW3Cで「Compute Pressure Level 1」が公開されています

Compute Pressure APIを使うと、PCのCPU負荷が4段階で確認できます。

  • Nominal: 負荷が低い状態
  • Fair: システムは正常に動作しており、追加のワークロードを実行できる
  • Serious: 負荷が高い状態。追加のワークロードを実行するとCriticalになりうる
  • Critical: 負荷が限界に近い状態

詳しいCPU情報はプライバシーの観点から公開しない設計になっています。

実行例

Compute Pressure API は現在Chromeの開発版で動作確認できます。
https://github.com/w3c/compute-pressure/blob/main/HOWTO.md を参考に実行しています。

サンプルでは、Observerを介して状態が変わる際にCallbackで負荷状態を出力しています。

function pressureObserverCallback(updates) {
  console.log("cpu pressure state = " + updates[0].state);
  console.log("timestamp = " + updates[0].time);
}

// Create observer with 1s sample rate.
observer = new PressureObserver(pressureObserverCallback, { sampleRate: 1 });

// Start observer.
await observer.observe("cpu");


実装のmemo

各 state の具体的なCPU使用率については仕様上では規定されていません。そこで、Chromeが実際にどのように判断しているかコードを一応確認しておきます。

今のところ、Nominal (30%未満), Fair (60%未満), Serious(90%未満), Critical (100%以下) となっているようです。ただし、より高度なアルゴリズムの利用も検討されているようですね。

  // TODO(crbug.com/1342528): A more advanced algorithm that calculates
  // PressureState using PressureSample needs to be determined.
  // At this moment the algorithm is the simplest possible
  // with thresholds defining the state.
  mojom::PressureState state = mojom::PressureState::kN4ominal;
  if (sample.cpu_utilization < 0.3)
    state = mojom::PressureState::kNominal;
  else if (sample.cpu_utilization < 0.6)
    state = mojom::PressureState::kFair;
  else if (sample.cpu_utilization < 0.9)
    state = mojom::PressureState::kSerious;
  else if (sample.cpu_utilization <= 1.00)
    state = mojom::PressureState::kCritical;
  else
    NOTREACHED() << "unexpected value: " << sample.cpu_utilization;

(https://source.chromium.org/chromium/chromium/src/+/main:services/device/compute_pressure/platform_collector.cc)

IETFでeBPFの標準化の議論

先月行われたIETF 115において、eBPFの一部ドキュメントをIETFからRFCとして出すか?という議論が行われました。

まだ議論の段階で結論は出ていないが、簡単にメモとして残しておく。

なお、僕自身はKernel, eBPF方面に明るいわけではない...

eBPF サイドミーティング

IETFでは会期中に特定トピックについて議論するサイドミーティングが行われます。IETF 115において「eBPF standardization side meeting」が開催されました。

eBPF Foundationのほうからは、Dave Thaler氏らを中心にeBPF Steering Committeeから数名と、IETF参加者がサイドミーティングに出席したようです。

概要

eBPF Foundation は、eBPF クロスプラットフォーム ドキュメントをどこで公開するかについて検討しています。主な候補は次の4つです:

  1. eBPF Foundation で発行
  2. eBPF Foundation によって公開され、ISO 番号が割り当てられるように ISO へ提出
  3. Independent Stream RFC として公開
  4. IETF RFC として公開

特に4点目をメインにディスカッションされました。技術的な部分はIETFでは関与しない想定だが、標準化のフローなどが適合するかなどが議論されました。一方でIETF内ではどのエリアで取り扱うかについて意見が出ましたが、INTやROUTINGが候補として上がっていました。

また標準化団体からの公開する必要性については、特にハードウェアベンダーが実装のために標準化仕様を望んでることが話されていました。

現在のeBPFドキュメントの管理

議論の中では現在のドキュメント管理状況についても説明されまいた。

現在、eBPFドキュメントは、Kernelのツリーに配置されています。

eBPF FoudationのGithubミラーリポジトリもあるようです (URL)。

パッチとしてebpf MLに投げられて、そこからリポジトリにマージされます。


(引用: eBPF side meeting @ IETF 115 - YouTube )

標準化候補のドキュメント

eBPFのうち次のドキュメントがIETFでの標準化候補としてあげられていました。

  • ISA
  • ELF file format
  • BPF type format
  • Compiler expectations
  • Verifier expectations
  • Cross-platform map types
  • Cross-platform program types
今後

引き続きさらなる議論が必要ということで、IETFにこの議論をするMLが出来ました。

subscribeはこちらから
Bpf Info Page