WebTransportの実験
WebTransportは、低レイテンシーで双方向のクライアントサーバーメッセージングを提供する新しいAPIです。その使用例と、実装の将来についてフィードバックを提供する方法の詳細をご覧ください。
公開日 • 更新日
この提案は、オリジンの試用期間中も変更され続けます。ブラウザの実装とこの記事の情報には相違がある可能性があります。
進化しつづけるこの提案の最新情報については、WebTransportの編集者の下書きをお読みください。
提案が安定したら、この記事と関連するコードサンプルを最新の情報で更新します。
背景
WebTransportとは?
WebTransportは、HTTP/3プロトコルを双方向トランスポートとして使用するWebAPIです。これは、WebクライアントとHTTP/3サーバー間の双方向通信を目的としています。データグラムAPIを介した信頼性の低いデータ送信と、ストリームAPIを介した信頼性の高いデータ送信の両方をサポートします。
データグラムは、強力な配信保証を必要としないデータの送受信に最適です。データの個々のパケットは、基盤となる接続の最大転送単位(MTU)によってサイズが制限され、正常に送信される場合とされない場合があり、転送される場合は任意の順序で届く可能性があります。これらの特性により、データグラムAPIは、低レイテンシーでベストエフォートのデータ送信に最適です。データグラムはユーザーデータグラムプロトコル(UDP)メッセージと考えることができますが、暗号化され、輻輳制御されています。
それとは対照的に、ストリームAPIは、信頼性の高い順序付けられたデータ転送を提供します。これらは、順序付けられたデータの1つ以上のストリームを送受信する必要があるシナリオに最適です。複数のWebTransportストリームを使用することは、複数のTCP接続を確立することに似ていますが、HTTP/3は内部で軽量のQUICプロトコルを使用するため、オーバーヘッドをあまりかけずに開閉できます。
ユースケース
これは、開発者がWebTransportを使用する可能性のある方法を小さくまとめたリストです。
- 小さな、信頼性の低い順不同のメッセージを介して、最小限のレイテンシーで定期的にゲームの状態をサーバーに送信します。
- 他のデータストリームに関係なく、最小限のレイテンシーでサーバーからプッシュされたメディアストリームを受信します。
- Webページが開いているときにサーバーからプッシュされた通知を受信します。
オリジントライアルプロセスの一環として、 WebTransportをどのように使用しようと考えているのかについて、詳しくお聞かせください。
この提案の概念の多くは、以前のQuicTransportオリジントライアルの一部として実験されましたが、Chromeの一部としてリリースされることはありませんでした。
WebTransportは、QuicTransportと同様のユースケースに役立ちますが、主な違いは、QUICではなくHTTP/3が、基盤となるトランスポートプロトコルであるということです。
WebTransportと他のテクノロジーの関係
WebTransportはWebSocketの代わりですか?
おそらくそうでしょう。WebSocketまたはWebTransportのいずれかを有効な通信プロトコルとして使用するユースケースがあります。
WebSocket通信は、単一の信頼できる順序付けられたメッセージストリームを中心にモデル化されています。これは、一部の種類の通信ニーズに適しています。これらの特性が必要なのであれば、WebTransportのストリームAPIでも提供されています。それに比べて、WebTransportのデータグラムAPIは、信頼性や順序を保証することなく、低レイテンシーの配信を提供するため、WebSocketの直接の代替ではありません。
データグラムAPIまたは複数の同時ストリームAPIインスタンスを介してWebTransportを使用すると、WebSocketで問題になることのあるヘッドオブライン(HOL)ブロッキングについて心配する必要がありません。さらに、基盤となるQUICハンドシェイクはTCP over TLSを起動するよりも高速であるため、新しい接続を確立するときにパフォーマンス上の利点があります。
WebTransportは新しいドラフト仕様の一部であるため、クライアントおよびサーバーライブラリを取り巻くWebSocketエコシステムは現在はるかに堅牢になっています。一般的なサーバー設定で「初期状態で」機能し、幅広いWebクライアントをサポートするものが必要な場合は、現時点ではWebSocketsがより良い選択と言えます。
WebTransportはUDP Socket APIと同じですか?
いいえ。WebTransportはUDP Socket APIではありません。WebTransportはHTTP/3を使用し、HTTP/3は「内部」でUDPを使用しますが、WebTransportには、暗号化と輻輳制御に関する要件があり、基本的なUDP Socket API以上のものになります。
WebTransportはWebRTCデータチャネルの代替手段ですか?
はい。クライアント/サーバー接続の場合はそうです。WebTransportは、WebRTCデータチャネルと同じプロパティの多くを共有していますが、基盤となるプロトコルは異なります。
WebRTCデータチャネルはピアツーピア通信をサポートしますが、WebTransportはクライアント/サーバー接続のみをサポートします。相互に直接通信する必要のある複数のクライアントがある場合、WebTransportは実行可能な代替手段ではありません。
一般に、HTTP/3互換サーバーを実行するには、WebRTCサーバーを維持するよりもセットアップと構成が少なくて済みます。これには、トランスポートを機能させるために複数のプロトコル(ICE、DTLS、およびSCTP)を理解する必要があります。WebRTCには、クライアント/サーバーのネゴシエーションの失敗につながる可能性のある、さらに多くの可動部分が伴います。
WebTransport APIは、Web開発者のユースケースを念頭に置いて設計されており、WebRTCのデータチャネルインターフェイスを使用するよりも、最新のWebプラットフォームコードを記述しているように感じるはずです。 WebRTCとは異なり、WebTransportはWeb Workers内でサポートされているため、特定のHTMLページに関係なくクライアント/サーバー通信を実行できます。WebTransportがストリーム準拠のインターフェースを公開するため、それがバックプレッシャー周りの最適化をサポートします。
ただし、満足のいくWebRTCクライアント/サーバーのセットアップがすでに機能している場合は、WebTransportに切り替えても多くの利点が得られない可能性があります。
試してみましょう
WebTransportを試す最善の方法は、互換性のあるHTTP/3サーバーをローカルで起動することです。(残念ながら、最新の仕様と互換性のある公開リファレンスサーバーは現在ありません。)その後、このページを基本的なJavaScriptクライアントで使用して、クライアント/サーバー通信を試すことができます。
APIの使用
WebTransportは、ストリームAPIなどの近代的なWebプラットフォームプリミティブの上に設計されました。これは、プロミスに大きく依存し、async
やawait
とうまく動作します 。
WebTransportオリジントライアルは、データグラムと、単方向ストリームと双方向ストリームの両方の3つの異なるタイプのトラフィックをサポートします。
サーバーへの接続
HTTP/3サーバーへの接続は、WebTransport
インスタンスを作成することで実現できます。URLのスキームはhttps
であることが推奨されます。ポート番号を明示的に指定する必要があります。
接続が確立されるまで待機するには、ready
プロミスを使用することをお勧めします。このプロミスは、セットアップが完了するまで実行されず、QUIC/TLSステージで接続が失敗した場合は拒否されます。
closed
プロミスは、接続が正常に閉じられたときに実行され、クローズが予期されていない場合は拒否されます。
クライアント表示エラー(たとえば、URLのパスが無効である場合)が原因でサーバーが接続を拒否した場合、 ready
は未解決のままですがclosed
は拒否されます。
const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);
// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
console.error('The HTTP/3 connection to ${url} closed due to ${error}.');
});
// Once .ready fulfills, the connection can be used.
await transport.ready;
データグラムAPI
サーバーに接続されたWebTransportインスタンスを作成したら、それを使用して、データグラムと呼ばれる個別のデータビットを送受信できます。
writeable
getterはWritableStream
を返します。これは、Webクライアントがサーバーにデータを送信するために使用できます。readable
getterはReadableStream
を返し、サーバーからのデータをリスンできるようにします。どちらのストリームも本質的に信頼性が低いため、書き込んだデータがサーバーで受信されない可能性があります。その逆も同様です。
どちらのタイプのストリームもデータ転送にUint8Array
インスタンスを使用します。
// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
const {value, done} = await reader.read();
if (done) {
break;
}
// value is a Uint8Array.
console.log(value);
}
Chromeは現在、 ReadableStream
の非同期イテレータを公開していません。当面は、getReader()
メソッドをwhile()
ループと組み合わせて使用することが、ストリームから読み取るための最善の方法です。
ストリームAPI
サーバーに接続したら、WebTransportを使用してストリームAPIを介してデータを送受信することもできます。
すべてのストリームの各チャンクはUint8Array
です。データグラムAPIとは異なり、これらのストリームには信頼性があります。ただし、各ストリームは独立しているため、ストリーム間のデータの順序は保証されません。
SendStream
SendStream
は、WebTransport
インスタンスのcreateSendStream()
メソッドを使用してWebクライアントによって作成され、SendStream
のプロミスを返します。
関連付けられたHTTP/3接続を閉じるには、WritableStreamDefaultWriter
のclose()
メソッドを使用します。ブラウザは、関連付けられた接続を実際に閉じる前に、保留中のすべてのデータの送信を試みます。
// Send two Uint8Arrays to the server.
const stream = await transport.createSendStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
await writer.close();
console.log('All data has been sent.');
} catch (error) {
console.error(`An error occurred: ${error}`);
}
同様に、サーバーにQUIC RESET_STREAMを送信するには、WritableStreamDefaultWriter
のabort()
メソッドを使用します。abort()
を使用している場合、ブラウザはまだ送信されていない保留中のすべてのデータを破棄する場合があります。
const ws = await transport.createSendStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.
ReceiveStream
ReceiveStream
がサーバーによって開始されます。ReceiveStream
の取得は、Webクライアントの2段階のプロセスです。まず、 WebTransport
インスタンスのreceiveStreams()
メソッドを呼び出します。これはReadableStream
を返します。ReadableStream
の各チャンクはその代わり、サーバーによって送信されたUint8Array
インスタンスを読み取るために使用できるReceiveStream
です。
async function readFrom(receiveStream) {
const reader = receiveStream.readable.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) {
break;
}
// value is a Uint8Array
console.log(value);
}
}
const rs = transport.receiveStreams();
const reader = rs.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) {
break;
}
// value is an instance of ReceiveStream
await readFrom(value);
}
ストリームが閉じたことを検出するには、ReadableStreamDefaultReader
のclosed
プロミスを使用できます。基盤のHTTP/3接続がFINビットで閉じられる場合、closed
プロミスは、すべてのデータが読み取られてから実行されます。HTTP/3接続が突然閉じられる場合(たとえばSTREAM_RESET
によって)、closed
プロミスは拒否します。
// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
console.log('The receiveStream closed gracefully.');
}).catch(() => {
console.error('The receiveStream closed abruptly.');
});
BidirectionStream
BidirectionalStream
は、サーバーまたはクライアントのいずれかによって作成されることがあります。
Webクライアントは、WebTransport
インスタンスのcreateBidirectionalStream()
メソッドを使用して作成できます。これにより、BidirectionalStream
のプロミスが返されます。
const stream = await transport.createBidirectionalStream();
// stream is a BidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream
WebTransport
インスタンスのreceiveBidirectionalStreams()
メソッドを使用して、サーバーによって作成されたBidirectionalStream
をリスンできます。これは、ReadableStream
を返します。代わりに、ReadableStream
の各チャンクは、BidirectionalStream
です。
const rs = transport.receiveBidrectionalStreams();
const reader = rs.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) {
break;
}
// value is a BidirectionalStream
// value.readable is a ReadableStream
// value.writable is a WritableStream
}
BidirectionalStream
は単に、SendStream
とReceiveStream
の組み合わせです。前の2つのセクションの例では、それぞれの使用方法を説明しています。
その他の例
WebTransportドラフト仕様には、すべてのメソッドとプロパティの完全なドキュメントとともに、いくつかのインライン例が追加で含まれています。
ChromeのDevToolsのWebTransport
残念ながら、 WebTransport用のChromeのDevToolsサポートは、オリジントライアルを開始する準備ができていません。このChromeの問題に「スター」を付けて、DevToolsインターフェースの更新について通知を受けることができます。
プライバシーとセキュリティに関する考慮事項
信頼できるガイダンスについては、ドラフト仕様の対応するセクションを参照してください。
フィードバック
オリジントライアルプロセス全体を通じ、このAPIを使用した感想や体験をあなたの考えや経験をChromeチームにお聞かせください。
API設計に関するフィードバック
APIについて、厄介なものや期待どおりに機能しないものはありますか?または、アイデアを実装するために必要なものが不足していませんか?
Web Transport GitHubリポジトリに課題を提出するか、既存の課題に考えを追加してください。
実装に問題がありますか?
Chromeの実装にバグが見つかりましたか?
https://new.crbug.comでバグを報告してください。再現するための簡単な手順とともに、できるだけ多くの詳細を含めてください。
APIの使用を計画していますか?
皆さんの一般サポートによって、Chromeは機能に優先順位を付け、他のブラウザベンダーにそれらをサポートすることがいかに重要であるかを示すことができます。
- オリジントライアルに登録して関心があることを示し、ドメインと連絡先情報を入力してください。
- ハッシュタグ「
#WebTransport
」を使用し、どこでどのようWebTransformを使用しているかを詳しくツイートしてください。
一般的なディスカッション
他のカテゴリのいずれにも当てはまらない一般的な質問や問題については、web-transport-devのGoogleグループを使用できます。
謝辞
この記事には、WebTransport Explainer、ドラフト仕様、および関連する設計ドキュメントからの情報が組み込まれています。その基盤を提供してくれた各作成者に感謝いたします。
この記事のヒーロー画像: Robin Pierre(Unsplash)。
更新日 • 記事を改善する