MagicOnion + quiche + Unityで gRPC over HTTP/3を実現する

-- Views

September 19, 26

スライド概要

C# Kaigi 2026登壇資料です
https://csharpkaigi.connpass.com/event/394163/

profile-image

Annulus Gamesのエンジニアの部分。Author of LitMotion, Alchemy, Lua-CSharp, etc.

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

MagicOnion + quiche + Unityで gRPC over HTTP/3を実現する > nuskey8/QuicHttpHandler 2026/09/19 @docomo R&D OPEN LAB ODAIBA C# Kaigi 2026 #csharpkaigi 1

2.

- @nuskey8 (a.k.a @annulusgames) - 大学生です - Unity・C#・RustのOSS開発やってます - インターンでパフォーマンスチューニングのお仕事をしてます #csharpkaigi # # 自己紹介 2

3.

- QUIC・HTTP/3とは何か - MagicOnionとgRPC over HTTP/3 - UnityでQUICを動かす #csharpkaigi # # セッションの内容 3

4.

# QUIC・HTTP/3とは何か #csharpkaigi 4

5.

- 従来のHTTP/1.1やHTTP/2ではTCPが使われていた - TCPは信頼性のある通信を提供する一方、いくつか問題があった - 順序を保証する都合上、パケットが欠けると再送を待機する必要がある (Head of Lineブロッキング問題) - HTTP/2ではストリームを多重化することができるが、結局TCPを使うので 1パケットのロスで全てのストリームが停止してしまう - UDPにはこれらの問題がない代わりに、単体では信頼性が必要な通信には向かない - 順序も再送も何も保証がない #csharpkaigi # # TCP・UDPの問題 5

6.

- UDP上に構築されたトランスポートプロトコル - ストリーム単位でデータの整合性を確保 - TCPのようなHead of Lineブロッキング問題が起きない - コネクションマイグレーションが可能 - Wi-fiからスマホの回線に変わるなどしてもコネクションを維持できる - コネクションの確立が速い - 1-RTTでハンドシェイクを行う #csharpkaigi # # QUICの登場 6

7.

- QUICをトランスポートプロトコルに利用した新しいHTTPのバージョン - HTTP/2をベースにしつつ、QUICの仕様に合わせて再構築 - ストリーム管理やウィンドウ制御はQUIC側に吸収 - 届いたパケットの到着順に依存しないように仕様を再設計(HPACK QPACKなど) 7 > - #csharpkaigi # # そしてHTTP/3へ

8.

# C#におけるQUIC・HTTP/3対応の現在位置 #csharpkaigi 8

9.

- MsQuicをベースとした実装が.NET 5で(内部用として)導入 - これはSystem.Net.Quicとして.NET 7で公開され、.NET 9で安定化された - https: learn.microsoft.com/ja-jp/dotnet/fundamentals/ networking/quic/quic-overview - MsQuicに依存する都合上、プラットフォームの制約がある - Windowsの場合はWindows11以降 - Linux/macOSではlibmsquicパッケージが必要 - それ以外のプラットフォームは基本的にサポート対象外 / / #csharpkaigi # # .NETでQUICを動かす 9

10.

- Kestrel(ASP.NET Core内部のWebサーバー)は.NET 7以降で正式にHTTP/3対応 - デフォルトでは無効なので以下のような設定が必要 - HTTPSが必須であることに注意 #csharpkaigi # # ASP.NET CoreでHTTP/3を動かす 10

11.

- HttpClientも.NET 7以降で正式にHTTP/3対応 - HttpVersion.Version30を指定すれば普通に動く - 内部的にはデフォルトのHttpMessageHandler実装である SocketsHttpHandlerがHTTP/3をサポートしている #csharpkaigi # # HttpClientでHTTP/3を使う 11

12.

- HttpClientは実はほとんどガワに過ぎず、実際の通信層は HttpMessageHandlerとして抽象化される - つまり、これを差し替えることで通信層を丸ごと置き換えることができる - これは後で出てくるので前提知識として覚えておいてください #csharpkaigi # # [補足] HttpMessageHandlerについて 12

13.

- QUIC・HTTP/3が.NET 7あたりからサポートされている - 実装はMsQuicを基盤としている - その都合上、QUICが利用できるプラットフォームに制約がある - デスクトップでは動くが、それ以外では動かない #csharpkaigi # # C#におけるQUIC・HTTP/3対応の現在位置 13

14.

# MagicOnionとgRPC over HTTP/3 #csharpkaigi 14

15.

- 「.NET プラットフォーム向けの双方向リアルタイム通信を提供する モダンなRPCフレームワーク」 - https: github.com/cysharp/MagicOnion - サーバー・クライアントをC#で統一 - .protoを使わず、C#のinterfaceをスキーマとした型安全なRPCを行う - 必要なコードはSource Generatorがコンパイル時に生成 / / #csharpkaigi # # MagicOnionとは? 15

16.

C#のinterfaceがそのままスキーマになる #csharpkaigi # # MagicOnionとは? 16

17.

- grpc-dotnetは他の言語に先んじてgRPC over HTTP/3に対応していた - 現在はデフォルトで対応、HttpVersion.Version30で明示もできる #csharpkaigi # # C#でgRPC over HTTP/3 17

18.

- MagicOnionの実装はASP.NET Coreおよびgrpc-dotnetの上に築かれている - 最新の.NETなら何もせずともHTTP/3で動かすことができる #csharpkaigi # # MagicOnionでgRPC over HTTP/3? 18

19.

? - MagicOnionを採用するプロダクトでは、クライアントがUnityであるケースも多い - モバイル向けタイトルでリアルタイム通信を行う場合、 QUIC・HTTP/3を利用することで得られる恩恵はとても大きい - UnityでもgRPC over HTTP/3したい、が 19 . . . . . . #csharpkaigi # # Unityは

20.

# UnityでQUICを動かす #csharpkaigi 20

21.

- Unityのランタイムは未だMono - .NET Standard 2.1相当の機能しか動かない - C#のバージョンも9.0のまま (実はちょっとしたハックで言語バージョンは上げられるが ) - Unity7でようやくCoreCLR移行が実現するが、もう数年はUnity6が主役 - CoreCLRになってもIL2CPPは必要 - モバイルやコンソールなどのプラットフォーム向けにIL2CPPは引き続き現役 21 . . #csharpkaigi # # Unityのランタイム事情

22.

- 当然.NET側のQUIC・HTTP/3サポートは使えない - なんならUnity6.3以前はHTTP/2すら標準サポートがない - 仮にCoreCLRが来たとしても、デスクトップ以外のプラットフォームでは厳しい - System.Net.Quicがモバイルで動くのかが怪しい - MsQuic自体は対応してる(動くだけで正式にサポートしているわけではない) ので動かせなくはなさそうだが… 22 . . . #csharpkaigi # # つまり

23.

- C#で自前でQUIC・HTTP/3を実装する? - 独自実装でQUIC・HTTP/3の膨大な仕様をカバーするのは非現実的 - 既存のライブラリに頼った方がいい - MsQuicをビルドして使う? - 実装の信頼性は最高レベル - C実装なのでポータビリティも高い - ただしMsQuicの実装範囲はQUICまで、HTTP/3部分は独自実装が必要 - どうしよう? #csharpkaigi # # 一体どうすれば? 23

24.

- Rust製のHTTP/3ライブラリをネイティブプラグインとして持ち込む - Rustの豊富なエコシステムを利用できる - ビルド周りもcargoがほとんど面倒を見てくれる - ただしコンソールを除く、今回はデスクトップ・モバイルのみを考えます #csharpkaigi # # そうだ、Rustを使おう 24

25.

- Cysharp/YetAnotherHttpHandler - Unity向けのHTTP/2対応のHttpMessageHandler実装 - Rustのhyper+rustlsをベースとした実装をFFIでC#に持ち込む #csharpkaigi # # Rust+Unityの先行事例 25

26.

- Rust製のQUIC・HTTP/3ライブラリはいくつかある - quiche、quinn、h3、などなど… - 具体的な比較は長くなるので割愛 - 詳しくは以下の記事が参考になります - https: qiita.com/takehara-ryo/items/1f3e19b54bd6fffcba77 / / #csharpkaigi # # ライブラリの選定 26

27.

- 信頼性が高く、パフォーマンス面にも優れたquicheを利用する - CloudflareによるQUIC・HTTP/3実装、モバイルでも動く - 実践投入されており信頼性が高い - そのままだとAPIが低レベルで扱いにくい - tokio-quicheをベースとして実装する - イベントループの管理は全てRust(tokio)側に置く - 高レベルなC APIを公開してC#側で叩くだけで済むように #csharpkaigi # # 今回の選択肢 27

28.

- 細かい実装については割愛 - C#側から非同期で扱うための工夫がちょいちょい入ってます - ほとんどAIが書いてくれています、いい時代になったものです #csharpkaigi # # Rust側の実装 28

29.

- Rust側で公開したC APIに合わせてFFIを手書きするのは大変 - Cysharp/csbindgenを用いてこれを自動化 - build.rsで設定するとビルド時に C#バインディングを自動生成する 29 . . #csharpkaigi # # バインディングの自動生成(csbindgen)

30.

- csbindgenで生成した低レベルAPIを叩くHttpMessageHandlerを実装 - これによりHttpClientの通信層をRust実装で差し替えられる - これだけで済めば良かったが 30 . . . #csharpkaigi # # HttpMessageHandlerとしてラップ

31.

- quicheの公開APIではHttpMessageHandlerの実装に必要な情報が足りない - Trailerヘッダが拾えない - これはgRPC対応に必須 - RESET_STREAMの理由が捨てられている - 接続直後のQLOGが取得できない - etc. - quicheをforkして改造を施すことで一旦解決 #csharpkaigi # # quiche側の改造 31

32.

- 通信のたびに同期I/Oはパフォーマンス的に許されない - Rust側からPipeに書き込ませ、C#側から読み取るのが基本 - 普通にC APIを作ると同期処理になるので、最初から非同期にすることを 前提に設計しないと難しい - TaskCompletionSource<T>でTaskに変換 - TaskCreationOptions.RunContinuationsAsynchronouslyを設定すること - これを忘れると継続処理が同期実行されるため、 Rust側のワーカースレッドをブロックする可能性がある #csharpkaigi # # System.IO.Pipelinesを用いた非同期I/O 32

33.

- HTTP/3で動くMagicOnionサーバーを立てておき、UnityからUnaryを叩いてみる #csharpkaigi # # Unityで動作させる 33

34.

#csharpkaigi # # Unityで動作させる 34

35.

- 今回の実装をnuskey8/QuicHttpHandlerとして公開 - Unity向けの想定ですが、一応.NET/Unityの両方で動きます - HTTP/3限定なので、HTTP/1.1や2も同時にサポートしたい場合は DelegatingHandlerでYetAnotherHttpHandlerなどにフォールバックしてください #csharpkaigi # # ライブラリ化しました 35

36.

# まとめ #csharpkaigi 36

37.

- .NET 7以降ではMsQuicベースのQUIC・HTTP/3実装がある - Unityでは動かせないため、quicheベースのRust実装を持ち込んで解決 - C#+Rustはいいぞ #csharpkaigi # # まとめ 37

38.

# Thank you for listening! #csharpkaigi 38