ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
HTTP/3とQUICによあるネットワーキングの加速
ウェブは絶えず変化しており、HTTPの次のメジャーバージョンが登場しています。HTTP/3がどのようにAppにおけるレイテンシを短縮し、信頼性を向上させるかについて確認し、その基盤となるトランスポート層のQUICが新しいトランスポート機能とマルチストリーミングコネクショングループを使用して、独自のカスタムプロトコルに新たなイノベーションをもたらすことを確認します。
リソース
関連ビデオ
Tech Talks
WWDC22
WWDC21
-
ダウンロード
♪ (HTTP/3とQUICによる ネットワーキングの加速) Rui Paulo: 皆さん こんにちは Ruiです 今日は同僚のEricと一緒に どのような方法を使えば アプリケーションのネットワークを 高速化できるか HTTP/3とQUICを使って 説明します iOS 15とmacOS Monterey で使える2つの新しいプロトコルです まず HTTPの進化と HTTP/3がどのようにして 性能を向上させるのかを見ます また HTTP/3の背後にある新しい トランスポートプロトコルである QUICについても説明します 次に URLSessionで HTTP/3を使用する方法と HTTP/3をサポートするように HTTPサーバを設定する 方法について説明します 最後にQUICを使用するための APIと QUIC上にカスタムネットワーク プロトコルを実装する 方法について詳しく説明します HTTPの進化について説明します リソースを取得する 必要があるとします 接続を設定し リクエストを送信し サーバが処理するのを待ち 応答を受信します ここで 最初のリソースが終了する前に 別のリソースをフェッチする場合は 同じプロセスを再度実行します 接続のセットアップ リクエストの送信 処理の待機 および応答の受信 この時間は濃い緑色で示されます 3番目のリソースの例を オレンジで示します 図に示すように 接続のセットアップには 多くの時間がかかります ひとつのHTTP/1接続を再利用 するとしたらどうでしょう? 接続のセットアップ時間を 節約しましたが リクエストを送信できるのは前の レスポンスが終了した後だけです これは head-of-line blockingと呼ばれます これまでHTTP実装は この問題を克服するために 多くの並列接続を使用してきました 並列HTTP接続の数は Appで設定することもできました しかし これはクライアントと サーバの両方に対して 非効率的なネットワーク 動作をもたらしてきました HTTP/2は 単一の接続上で複数の ストリームを多重化して Head-of-Line Blockingを 解決します リクエストはより早く送信され 異なるストリームからの データをインターリーブできます これにより アイドル待機時間が大幅に 削減されるため単一のTCP接続を より効率的に使用できます HTTP/3を使用すると 接続のセットアップが遥かに 高速になるためリクエストをより 早く送信できます しかし HTTP/3の 利点はそれだけではありません HTTP/3ストリームは独立しており すべてのストリームが 1つのTCP接続を共有する HTTP/2とは異なります ほとんどのネットワークでは パケットは失われます これは 無線ネットワーク上の 通常のイベントであり ネットワークの容量を検出する 自然な部分です HTTP/2では全てのHTTP/2 ストリームが単一のTCP接続を 共有するためパケット損失が多くの ストリームに影響を与えかねません HTTP/3では 対応するHTTPストリーム のみが影響を受けます 他のストリームに属するデータは より早く配信できます HTTP/3がより早く接続を 確立する方法 そしてパケット損失に 上手く対処方法を示しました これらの改善は 基礎となる 転送プロトコルQUIC QUICはインターネット技術 タスクフォースで標準化された 信頼性の高い新しい 通信プロトコルです TCPと同じ概念に基づいていますが エンドツーエンド暗号化 多重化ストリームおよび認証を 提供しています QUICの安全性は周知の TLS 1.3の上に構築され QUICの主な利点は 性能の向上です では QUICがそれを実現する 方法を見てみましょう QUICはTLS 1.3に 依存して安全な通信を行い 使い慣れた TCPスリーウェイ通信が不要で ハンドシェイク時間が単一の ラウンドトリップに短縮されます 多重ストリームはQUICの 重要な概念であるため head-of-line blockingの 影響を受けません QUICエンドポイントは受信した パケットに関するより 複雑な情報を他のエンドポイントに 通信することができ TCPの制限によって 妨げられることがないため QUIC接続の損失回復が 向上します またこのプロトコルでは 接続の移行もサポートされているため セルラーネットワークと Wi-Fi間などの セッションを再確立することなく 異なるネットワーク インターフェイス間で 接続をシームレスに移動できます ネットワーク遅延の詳細については "Appにおけるネットワーク遅延の低減" セッションをご覧ください AppでHTTP/3を使う 方法について話しましょう URLSessionを 使用している場合は iOS 15および macOS Monterey 以降のAppはHTTP/3が有効に なった状態で出荷されています サーバ上でHTTP/3を 有効にしておけば 問題ありません 次のHTTP/3 RFC バージョンと 以前のHTTP/3 Draft 29の 両方がサポートされます HTTP/3を利用していることを 確認する方法は? ツールを使って調べましょう Xcode 13ではHTTP トラフィックを検査するための 新しいツールをネットワーキング プロファイリングテンプレートに 導入しています URLSessionに直接 接続するので セットアップは必要ありません ツールを使ってAppが HTTP/3またはそれ以前の HTTPバージョンを使用しているかを 調べることができます iOS Appを立ち上げて 犬の写真セットを取得します 次に HTTPヘッダを検査して サーバがHTTP/3に 通知する方法を調べます 次に ネットワークプロファイル テンプレートを選択します
左上の記録をクリックしましょう HTTPトラフィックの記録による プライバシーへの影響を示す プロンプトが表示されます 同意した後 ツールはHTTPトランザクションの 記録を開始します
次にツールはApp毎 およびドメイン毎の 全HTTPトランザクションの プロットを表示します これで必要なデータを すべて収集できました 左上にある一時停止ボタンを クリックします
使用するドメインを選択します これを行うには オプションボタンを押しながら HTTPトランザクションを クリックし ドメインを選択します
HTTPトランザクションの 詳細を表示するように ツールを設定する必要があります そのためには左側のメニューに HTTPトランザクションが 表示されていることを確認します
最初のリクエストを選択します 右にスクロールすると このトランザクションが使用した HTTPのバージョンを示す HTTPバージョン列が表示されます まだHTTP/2を使っていますが なぜですか 右側には応答ヘッダを含む 拡張詳細ビューがあります これが答えです サーバはHTTP代替 サービスを使用して HTTP/3のサポートを 通知しました
URLSessionは通知され ないHTTP/3を使用しません この例ではHTTP/3は Alt-Svc HTTPヘッダを 介して通知されています HTTPサーバがこのヘッダを 使用してHTTP/3のサポートを 通知するのは一般的です この情報は将来の接続のために 記憶され これを 「サービスディスカバリ」 と呼びます では もう一度Appを記録しましょう
いったんAppを再起動すると 同じHTTPトランザクションの セットが発生します ここでも ツールを一時停止できます
もう一度ズームインして最初の トランザクションをチェックします サーバがHTTP/3をサポート していたことを思い出したので 現在はHTTP/3を 使用しています HTTP/3サービス検出は Appに対して透過的です HTTP/3サーバサポートの 検出は2つの方法で行われます 推奨される方法は HTTPSリソースレコードを 介してHTTP/3のサポートを 通知するように DNSサーバを設定することです h3文字列を使用して HTTP/3を通知するように アプリケーション層プロトコルを 設定するだけです また サーバを設定して 代替サービスを使用して HTTP/3を通知する新しい ヘッダを追加するように サーバを設定する 必要もあります サーバはHTTP/3を通知する Alt-Svcヘッダを 送信する必要があります これにはポート番号とサービスの 最大経過時間 秒単位が含まれます DNSレコードの利点は 情報がDNSにあるため アプリケーションがサーバに 初めて接続しようとしたときに HTTP/3接続を確立できます サーバがHTTP/3をサポート していることがわかっていて 検出プロセスを高速化したい場合は assumesHTTP 3 Capableを プロパティを使用できます これによりHTTPスタックは HTTP/3サーバですが HTTP/3が使用されることを 保証しません ネットワークがまだHTTP/3を ブロックしているか サーバが実際にHTTP/3をサポート していない可能性があります その場合はHTTP/2に戻ります HTTPを使用すると顧客は 各リソースの優先順位を指定できる リソースは関連していることが 多いため 優先順位によって クライアントのニーズに基づいて サーバは一部のリソースを 他のリソースよりも先に 送信できます たとえば Webページのレンダリングに 最も影響を与えるリソースに 優先順位を付けることで Webブラウジングのユーザー 体験を向上させることができます 優先度スキームはHTTP/2で 導入されましたが その複雑さのために あまり評価されませんでした そのため 古いプライオリティモデルは HTTP/3から削除されました HTTP/3スタックでは HTTPヘッダに依存する より単純な新しいモデルが 使用されます このモデルでは 優先順位が指定されています 緊急度パラメータを 0から7に設定して オプションの増分配信パラメータが あります URLSessionを使用する場合 優先順位をサポートする APIは同じままです 優先度プロパティを使用して HTTP優先度を指定し 緊急度を使用して サーバに通信します インクリメンタル配信は prefersIncrementalDelivery プロパティを使用して有効にでき デフォルトのプライオリティは3です URLSessionは 便利なAPIであるかどうかに 応じて差分配信を推測します async dataメソッドの ように使用されます リソース全体をダウンロードする まで処理できないコンテンツを Appがダウンロードする場合は このプロパティを falseに設定する必要が あります リクエストの送信後に リソースの優先順位を動的に 変更することも サポートされています 例えば 低い優先度で写真をプリフェッチし ユーザーがAppのそのセクションに 移動したときに その優先度を上げることができます 次に 同僚のEricが カスタムのネットワーク プロトコルを変更して QUICを採用する方法について 説明します ありがとうございました ありがとう Rui 前述したようにHTTP/3は QUICの上に構築されており HTTP/2に見られるものと 同様のストリームの多重化を 提供しますが基礎となる トランスポートとして 単一のTCP接続を 共有することで 生じる問題はありません QUICトランスポート接続 またはQUICトンネル 複数の単方向または双方向 QUICストリームの データを多重化します ストリームはどちらの エンドポイントでも作成でき 他のストリームと同時に インターリーブされたデータを 送信できTCPによって提供 される従来のストリームと 同様の状態を持ちます 何よりも優れているのは QUICにTLS 1.3 セキュリティが搭載しネットワーク 状況の変化にも対応できる点です これらの機能は HTTP以外にも役立ちます アプリケーションがリクエスト レスポンスに基づかないデータを 交換している場合 基礎となる トランスポートコンテキストを共有 する多重ストリームを持つこと又は その他のカスタムプロトコルを実装 していることから メリットが得られる 可能性があります ピアツーピア通信やRPC呼び出しなど AppにQUICトランスポートを 使用することを検討してください iOS 15と macOS Montereyで NWProtocolQUICは Network.frameworkで 提供されるその他の組み込み プロトコルに加わります 接続作成にQUICを使うことは よく知られています エンドポイントと新しく 使用可能になった QUICパラメータを 指定するだけです これらのパラメータは サーバとネゴシエートする アプリケーション層プロトコル であるALPN文字列を指定します 通常と同じように 状態更新ハンドラを設定します 接続が進行し準備が整ったときに 応答できるように 最後に 状態の更新や その他のコールバックに使用する ディスパッチキューで 接続を開始します これでQUICストリームが 確立されたので 他のNWConnectionと 同じように データを送受信できます send関数を使用してリモート エンドポイントに送信する データを指定し 完了時に後続の送信を スケジュールします receiveを使用して着信データを 処理し その後の受信が完了したときに スケジュールします Network.frameworkに 昨年接続グループオブジェクトを 導入し 複数の接続が関連したり グループ化されている状況を 扱いやすくしました 基礎となるトランスポート コンテキスト またはトンネルで 多重化されるQUICストリームは その関係に基づいて 論理的にグループ化され 新しいグループタイプ NWMultiplexGroupで 使用できます 接続グループは他の Network.framework オブジェクトと同様の ライフサイクルに従います これによりQUICストリームに よって共有される基盤となる QUICトンネルの状態を 判断できます また 特定のQUICトンネルから 新しい発信ストリームを作成したり リモートエンドポイントによって 開始された新しい着信ストリームを 受信したりできます 多重プロトコルの接続グループを 作成するには 多重グループ記述子を使用します この例では ポート443で example.comに対する グループ記述子を作成します 次に 記述子とQUIC パラメータを使用して NWConnectionGroupを 作成し ALPN文字列を指定します NWConnectionと同様に 状態更新ハンドラを設定しますが 今回は 個々のストリームの状態ではなく 基盤となるQUICトンネルの 状態を追跡します 最後に コールバックキューを 提供する 接続グループを開始します 新しい発信ストリームを 作成するにはグループから NWConnectionを 初期化するか グループでextract 関数を呼び出します リモートエンドポイントによって 開始される着信ストリームは グループに新しい接続ハンドラを 設定することによって 処理できます これらの接続は状態ハンドラを使用 して通常どおり設定できます 今度はストリームの状態を追跡し コールバックに使用する キューから始めます 他のプロトコルと同様にパラメータの オブジェクトを作成するときに QUIC.Optionsを使用して 設定できます QUICの場合 QUIC仕様にリストされている トランスポートパラメータを 構成でき 接続グループからストリームを 作成するときに個々のストリームの プロパティをカスタマイズ することもできます 例えば 新しい単一方向ストリームを 作成する場合などです NWListenerを使用して App内でサーバを実行中の場合は この機能が拡張され 新規の ConnectionGroupHandlerを 介して新しい着信QUICトンネルを 受信できるようになりました サーバへの新しいQUIC トンネルが確立されるたびに 新しい ConnectionGroupHandlerが 呼び出されます そのハンドラ内で 状態の更新を受信するように グループを通常どおり 設定できます これは先ほど説明した新しい 接続ハンドラを設定するのにも 適した場所です このトンネルで開かれている後続の ストリームを受信する場合は コールバックに使用する キューを使用して グループを開始すると すべての設定が完了します 最後に NWProtocolMetadataを 使用してストリームに関する 情報にアクセスできます 例えば 新規作成のストリームの ストリームIDを 確認することができます またストリームの処理が終了し カスタムプロトコルで アプリケーションエラーコードが 定義されている場合は ストリームをキャンセルする前に メタデータを使用して リモートエンドポイントに エラーを通知できます ここまでは 新しい NWMultiplexGroup タイプを使用して QUICトンネルを作成して 管理する方法と そのグループから QUICストリームごとに個別の NWConnectionを 作成する方法について説明しました NWListenerを使用して 着信トンネルをリッスンし 結果の接続グループを使用して 新しい 着信ストリームを受信できます これらのストリームでは 他の接続と同様にデータを送受信できます また QUICプロトコル オプションを使用して トランスポートパラメータを指定し ストリームを構成し QUICプロトコル メタデータを使用して ストリームを検査し QUIC固有の情報を リモートエンドポイントに 通信できます QUICを採用してAppの ネットワーキングを改善しました では 上手くいっているかどうかは どうすれば分りますか qlogファイルを出力する新しい 環境変数を使用して デバッグ中にアプリケーションを 起動できます qlogはIETFで提案された 新規標準化されたロギング形式です これにより QUIC接続の動作に関する情報を 従来のパケットキャプチャよりも さらに詳細にエクスポートできます テスト実行後 Xcodeの デバイスウィンドウを使用して 分析用のqlogファイルを含む アプリケーションの コンテナをダウンロードできます また QUIC接続の振る舞いを より簡単に内省できるようにする さまざまなオープンソースの 視覚化があります 今回は HTTP/3がHTTP トラフィックに提供する 改善点を検証しました 最新のネットワークAPIの ユーザーには既に デフォルトで有効になっているので サーバ上のHTTP/3で ネットワークの状態の変化に対する 向上した性能と回復力を 利用することができます HTTP以外のカスタムネット ワークプロトコルを使用している 場合は Network.frameworkに 組み込まれた新しい多重化 プロトコルサポートを使用して NWConnectionGroupとの QUIC接続を作成します どのプロトコルを使用している 場合でも 新しいデバッグツールを使用して 次世代のネットワークプロトコルの 優れた利点を視覚化できます ご覧いただきありがとうございます ♪
-
-
13:20 - Using QUIC in your app
// Create a connection using QUIC let connection = NWConnection(host: "example.com", port: 443, using: .quic(alpn: ["myproto"])) // Set the state update handler to be notified when the connection is ready connection.stateUpdateHandler = { newState in switch newState { case .ready: print("Connected using QUIC!") default: break } } // Start the connection with callback queue connection.start(queue: queue)
-
15:08 - Establish a tunnel with NWMultiplexGroup
// Establish a tunnel with NWMultiplexGroup // Create a group let descriptor = NWMultiplexGroup(to: .hostPort(host: "example.com", port: 443)) let group = NWConnectionGroup(with: descriptor, using: .quic(alpn: ["myproto"])) // Set the state update handler to be notified when the group is ready group.stateUpdateHandler = { newState in switch newState { case .ready: print("Connected using QUIC!") default: break } } // Start the group with callback queue group.start(queue: queue)
-
15:45 - Manage streams with NWConnectionGroup
// Manage streams with NWConnectionGroup // Create a new outgoing stream let connection = NWConnection(from: group) // Receive new incoming streams initiated by the remote endpoint group.newConnectionHandler = { newConnection in // Set state update handler on incoming stream newConnection.stateUpdateHandler = { newState in // Handle stream states } // Start the incoming stream newConnection.start(queue: queue) }
-
16:43 - Receive incoming QUIC tunnels from NWListener
// Receive incoming QUIC tunnels from NWListener // Set the new connection group handler listener.newConnectionGroupHandler = { group in group.stateUpdateHandler = { newState in // Handle tunnel states } group.newConnectionHandler = { stream in // Set up and start new incoming streams } group.start(queue: queue) }
-
17:22 - Access QUIC metadata
// Access QUIC metadata to learn about and modify streams // Find the stream ID of a particular QUIC stream if let metadata = connection.metadata(definition: NWProtocolQUIC.definition) as? NWProtocolQUIC.Metadata { print("QUIC Stream ID is \(metadata.streamIdentifier)") // Some time later... // Set the application error, if appropriate, before cancelling the stream metadata.applicationError = 0x100 connection.cancel() }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。