Posted at

.NET CoreでMagicOnionを動かしてみた


MagicOnionとは

gRPCを用いた.NET/Unity間のリアルタイム通信ライブラリです

- https://github.com/Cysharp/MagicOnion

READMEでは、Windows上で動かすことを前提に書かれていたりしますが、

Linux/Macでも問題なく動作します。

(Install-Package コマンドなどが記載されているので)


検証内容

今回はUnityは一切使用しません

MagicOnionとはどういうものかをREADMEに沿って検証するのみとなっています


検証環境


  • Mac OS Mojave 10.14.2

  • .NET Core 2.1.301


サンプルプログラムを動かす

READMEに沿って、サーバー/クライアントのコードを動かしてみます


準備

サーバー側/クライアント側の両方のConsoleプロジェクトを作成します


  • サーバー側

$ mkdir Server

$ cd Server
$ dotnet new console
$ dotnet add package MagicOnion


  • クライアント側

$ mkdir Client

$ cd Client
$ dotnet new console
$ dotnet add package MagicOnion

これで準備完了です


サーバー側実装

https://github.com/Cysharp/MagicOnion#quick-start

こちらに記載されている、サーバー側プログラムをそのままコピーします

(Program.csとMyFirstService.cs)


クライアント側実装

軽く動作検証するだけですので、ちょっとだけコードを変更し以下のようにします

また、クラアント側には MyFirstService の実態は不要でインターフェースを定義したファイルだけあれば良いです

(後述しますが、これがIDLとなります)

class Program

{
static void Main(string[] args)
{
// standard gRPC channel
var channel = new Channel("localhost", 12345, ChannelCredentials.Insecure);

// get MagicOnion dynamic client proxy
var client = MagicOnionClient.Create<IMyFirstService>(channel);

// call method.
var result = client.SumAsync(100, 200).GetAwaiter().GetResult();

Console.WriteLine("Client Received:" + result);
}
}

手を加えた箇所は以下のところです

本来はasyncで非同期実行するところですが、GetAwaiter().GetResult() と書くと同期的に処理が終わるまで待機してくれます

(メインスレッドが固まるのでリリース開発版などでの利用はおすすめしません...)

client.SumAsync(100, 200).GetAwaiter().GetResult();


動かしてみる


サーバープログラムの起動

まず、サーバー側プログラムを動かします。

単純な検証ですので dotnet run コマンドで実行するだけです

$ cd Server

$ dotnet run
D0204 17:50:33.569109 Grpc.Core.Internal.UnmanagedLibrary Attempting to load native library "/Users/Hogehoge/.nuget/packages/grpc.core/1.17.0/lib/netstandard1.5/../../runtimes/osx/native/libgrpc_csharp_ext.x64.dylib"
D0204 17:50:33.672423 Grpc.Core.Internal.NativeExtension gRPC native library loaded successfully.

サーバーが待機状態で起動します


クライアントプログラムの起動

$ cd Client

$ dotnet run
Client Received:300

サーバーからのレスポンスを受けることが確認できます

また、サーバー側のログにも以下のように表示され、リクエストを処理できたことが確認できます



D0204 17:52:40.951573 Received:100, 200

特に苦労することもなくあっさり動いてくれました


ちょっと動かしただけでわかるメリット


サーバー/クライアント間でのIDLが不要!

通信仕様を共有するために、中間言語で書かれたIDLだったり、SwaggerなどでのAPI仕様を共有することが多いですが、MagicOnionでは、C#のインターフェースファイルをクライアントに渡すだけでサクッと通信ができます


デメリット

当たり前ですがすべてC#縛り...


その他1

コンパイル時に、

MyFirstService.cs(22,39): warning CS1998: この非同期メソッドには 'await' 演算子がないため、

同期的に実行されます。'await' 演算子を使用して非ブロッキング API 呼び出しを待機するか、
'await Task.Run(...)' を使用してバックグラウンドのスレッドに対して
CPU 主体の処理を実行することを検討してください。

という警告が出ますが、無視で。作者のサイトでも公式に言及されています

(Generalized async return types (Task-like) は別途勉強しておかないと...)

http://neue.cc/2017/04/06_551.html


その他2

最近は、BlazorというWebのフロントエンドをC#で書けるものも出てきているので、

MagicOnionはUnity以外でも用途は色々とあるのではとちょっと思いました

https://blazor.net/