WCFのパイプ通信を .NET 5に向けてgRPCへ置き換える話

2.8K Views

March 15, 22

スライド概要

C# Tokyo オンライン LT 大会 2021/01の発表資料
https://csharp-tokyo.connpass.com/event/200125/

profile-image

会社勤めのSE・プログラマです。個人としての情報発信も行っており、このアカウントはその用途で使用します。同一ID「suusanex」でGitHub・はてな等でも発信しています。

シェア

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

各ページのテキスト
1.

WCFのパイプ通信を .NET 5に向けて gRPCへ置き換える話

2.

自己紹介  ID:suusanex( connpass・Twitter・GitHub共通)  名前:須藤圭太  サイエンスパーク株式会社という独立系ソフトウェアベンダーに所属  4年ほど受託開発で、上流から下流まで全部を回す  ここ6年ほどは、自社製品開発を担当  Windowsアプリ開発のネタが多い  勉強会もやってます。最近は開けていませんがそのうち再開します  https://yokohama-win-dev-tips.connpass.com/  https://sciencepark.connpass.com

3.

WCFのパイプ通信とは何の話?  Windowsアプリ開発で、ピンポイントで便利だった実装方法  Windowsサービスとデスクトップアプリで高速な通信をしたい  しかも双方向通信したい  そのためのパイプ通信を、.NET Frameworkでは WCFで簡単に実装できた  WCFらしく、クラスにメソッドを定義して 関数呼び出しの感覚で使える

4.

しかし、WCFは.NET 5で引退  .NET 5ではWCFサーバーを実装出来ないし、今後もサポート予定なし  MSも丁寧なドキュメントでgRPCへの移行を促している  ASP.NET Core gRPC に WCF を移行する理由 Microsoft Docs https://docs.microsoft.com/ja-jp/aspnet/core/grpc/why-migrate-wcf-to-dotnetgrpc?view=aspnetcore-5.0

5.

gRPCというやつに乗り換えよう!  気になるポイントがいくつかある  パイプ通信できる?  関数呼び出しの感覚で使える?  双方向通信できる?  .NET Frameworkのクライアントから呼べる?  こういう疑問に答えつつ、軽くだけ実装方法を紹介します

6.

パイプ通信できる?  できない  しかし、localhostでのTCP/IP通信になるので、十分に速いはず  通信セッション開始・通信1回・通信セッション終了までを1セットとして計測  注意:開発環境での雑な実測結果  遜色なし WCF(Pipe) gRPC 初回の通信 0.1s 0.2s 2回目の通信 0.02s 0.005s 10回連続通信 0.2s 0.05s

7.

関数呼び出しの感覚で使える?  近いことはできる  一方的に送るだけなので、戻り値という考え方は無い  リクエストとレスポンスをペアで定義すれば良い  使用感はAsyncのメソッドと同じ

8.

双方向通信できる?  できる  Bidirectional streaming RPC  最初のSubscribeで2つのストリームを作る  サーバーとクライアントがそれぞれストリームを読む

9.

.NET Frameworkのクライアントから呼べ る?  できる  同じ定義を共有することで、.NET 5のクライアントとも共存可能

10.

いけそう  気になる点は問題なかったので、移行して行けそう  移行していく上での実装方法を軽く紹介します

11.

少し詳しい実装方法 コマンドの定義  WCFのコントラクトの代わりに、protoファイルで定義を書く  色々書き方があるが、下記のようにするとWCFと同じイメージで使える クラス(イメージ) メソッド(イメージ) message UserSesionToServiceRequest { oneof action { RegisterUserSessionRequest RegisterUserSession = 1; GetDataRequestParam GetDataRequest = 2; SendDataResponseParam SendDataResponse = 3; } メソッドのパラメータ(イメージ) } message RegisterUserSessionRequest{ int32 sessionId = 1; }

12.

少し詳しい実装方法 送信側  ProtoファイルからC#のクラスを生成してくれる  開いたストリームにクラスをWriteすると送信になる クラス用のストリーム クラス(イメージ) await m_DuplexStream.RequestStream.WriteAsync(new UserSesionToServiceRequest { RegisterUserSession = new RegisterUserSessionRequest { SessionId = Process.GetCurrentProcess().SessionId } メソッドのパラメータ }); メソッド(イメージ) (イメージ)

13.

少し詳しい実装方法 受信側  ProtoファイルからC#のクラスを生成してくれる  開いたStreamをReadすると、受信したら制御が戻る クラス(イメージ) クラス用のストリーム await foreach (var req in subscribe.RequestStream.ReadAllAsync(cancellationToken)) { switch (req.ActionCase) { case UserSesionToServiceRequest.ActionOneofCase.RegisterUserSession: { var val = req.RegisterUserSession; メソッドのパラメータ (イメージ) メソッド(イメージ)

14.

まとめ  全く同じではないが、WCFに近いイメージでプロセス間通信を実現できる  同期でレスポンスを待つクラスを作れば、影響軽微で差し替えもできそう  WCFを使っている人は、 .NET 5に向けて乗り換えを模索していきましょう