HttpClient で HTTP/3 を使用する

HTTP/3 は、最近標準化された HTTP の 3 番目のメジャー バージョンです。 HTTP/3 では、HTTP/1.1 および HTTP/2 と同じセマンティクスを使用します。つまり、同じ要求メソッド、状態コード、メッセージ フィールドがすべてのバージョンに適用されます。 異なる点は、基になるトランスポートにあります。 HTTP/1.1 と HTTP/2 では、どちらもトランスポートとして TCP が使用されます。 HTTP/3 では、QUIC という HTTP/3 と共に開発されたトランスポート テクノロジが使用されます。

HTTP/3 と QUIC はどちらも、HTTP/1.1 および HTTP/2 と比較していくつかの利点があります。

  • 最初の要求の応答時間が短縮されます。 QUIC と HTTP/3 では、接続をネゴシエートする際にクライアントとサーバー間のラウンドトリップ回数がより少なくなります。 最初の要求がより速くサーバーに到達します。
  • 接続パケットの損失が発生したときのエクスペリエンスが向上しました。 HTTP/2 では、1 つの TCP 接続を介して複数の要求が多重化されます。 接続でのパケットの損失は、すべての要求に影響します。 この問題は、"ヘッドオブライン ブロッキング" と呼ばれます。 QUIC ではネイティブ多重化が提供されるため、失われたパケットはデータが失われた要求のみに影響します。
  • ネットワーク間の移行がサポートされます。 この機能は、モバイル デバイスの場所が変わると頻繁に WiFi と携帯ネットワークを切り替えるモバイル デバイスで便利です。 現在、HTTP/1.1 と HTTP/2 の接続では、ネットワークを切り替えるときにエラーが発生して失敗します。 アプリまたは Web ブラウザーでは、失敗した HTTP 要求を再試行する必要があります。 HTTP/3 を使用すると、ネットワークが変更されたときにアプリまたは Web ブラウザーをシームレスに続行できます。 HttpClient と Kestrel は、.NET 7 ではネットワーク移行がサポートされていません。 今後のリリースで利用可能になる可能性があります。

重要

HTTP/3 を利用するように構成されたアプリは、HTTP/1.1 および HTTP/2 もサポートするように設計する必要があります。 HTTP/3 で問題が特定された場合は、.NET の今後のリリースでその問題が解決されるまで、HTTP/3 を無効にすることをお勧めします。

HttpClient 設定

HTTP バージョンは、HttpRequestMessage.Version を 3.0 に設定することで構成できます。 しかしながら、すべてのルーター、ファイアウォール、プロキシで HTTP/3 が適切にサポートされているわけではないので、HTTP/3 を HTTP/1.1 および HTTP/2 と一緒に構成することをお勧めします。 HttpClient では、次を指定してこれを行います。

プラットフォームの依存関係

HTTP/3 では、トランスポート プロトコルとして QUIC が使用されます。 HTTP/3 の .NET 実装では、MsQuic を使用して QUIC の機能が提供されます。 その結果、.NET での HTTP/3 のサポートは、MsQuic プラットフォームの要件に依存します。 MsQuic のインストール方法の詳細については、QUIC プラットフォームの依存関係に関する記事を参照してください。 HttpClient が実行されているプラットフォームに HTTP/3 の要件がすべて備わっていない場合は、無効になります。

HTTPClient の使用

次のコード例は、最上位レベルのステートメントを使用し、要求で HTTP3 を指定する方法を示しています。

// See https://aka.ms/new-console-template for more information
using System.Net;

using var client = new HttpClient
{
    DefaultRequestVersion =  HttpVersion.Version30,
    DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact
};

Console.WriteLine("--- localhost:5001 ---");

HttpResponseMessage resp = await client.GetAsync("https://localhost:5001/");
string body = await resp.Content.ReadAsStringAsync();

Console.WriteLine(
    $"status: {resp.StatusCode}, version: {resp.Version}, " +
    $"body: {body.Substring(0, Math.Min(100, body.Length))}");

.NET 6 での HTTP/3 サポート

.NET 6 では、HTTP/3 仕様がまだ最終決定されていないため、HTTP/3 は "プレビュー機能" として使用できます。 動作やパフォーマンスは、.NET 6 の HTTP/3 で問題がある可能性があります。 プレビュー機能の詳細については、「プレビュー機能の仕様」を参照してください。

.NET 6 で HTTP/3 のサポートを有効にするには、HttpClient で HTTP/3 を有効にするために、プロジェクト ファイルに RuntimeHostConfigurationOption ノードを含めます。

<ItemGroup>
    <RuntimeHostConfigurationOption Value="true"
        Include="System.Net.SocketsHttpHandler.Http3Support" />
</ItemGroup>

または、アプリ コードから System.AppContext.SetSwitch を呼び出すか、環境変数 DOTNET_SYSTEM_NET_HTTP_SOCKETSHTTPHANDLER_HTTP3SUPPORTtrue に設定します。 詳しくは、.NET の環境変数: DOTNET_SYSTEM_NET_HTTP_* に関する記事をご覧ください。

HTTP/3 の構成フラグを必要とする理由は、バージョン ポリシー RequestVersionOrHigher を使用する場合に将来的にアプリが壊れないように保護するためです。 HTTP/1.1 と HTTP/2 を現在使用しているサーバーを呼び出す場合、サーバーが後で HTTP/3 にアップグレードすると、クライアントは HTTP/3 を使用しようとし、規格が最終版ではないため、.NET 6 のリリース後に変更されることがあるため、互換性がない可能性があります。

.NET 6 は libmsquic の 1.9.x バージョンとのみ互換性があります。 ライブラリの破壊的変更により、Libmsquic 2.x は .NET 6 と互換性がありません。 セキュリティ修正プログラムを組み込む必要があるとき、Libmsquic では 1.9.x への更新プログラムを受け取ります。

HTTP/3 サーバー

HTTP/3 は、.NET 6 (プレビューとして) および .NET 7 (完全にサポートされています) の Kestrel サーバーを使った ASP.NET でサポートされています。 詳細については、「ASP.NET Core Kestrel Web サーバーで HTTP/3 を使用する」を参照してください。

パブリック テスト サーバー

Cloudflare は、https://cloudflare-quic.com でクライアントをテストするために使用できる HTTP/3 用のサイトをホストしています。

こちらもご覧ください