2021-11-12に更新

C#(.Net 6)でgRPCサーバー on Mac

.Net 6 も出たし……と思い、C# で gRPC のサンプルをMacで動かそうとしたらエラーで落ちてちょっと戸惑ったので、手順を書いておきます。

手順

テンプレートからプロジェクトを作る

gRPCのテンプレからプロジェクトを作ります。

$ dotnet new grpc -o GrpcGreeter

実行(落ちる)

普通に実行します。するとMacでは落ちます。

$ cd GrpcGreeter
$ dotnet run
ビルドしています...
Unhandled exception. System.IO.IOException: Failed to bind to address https://localhost:7229.
 ---> System.AggregateException: One or more errors occurred. (HTTP/2 over TLS is not supported on macOS due to missing ALPN support.) (HTTP/2 over TLS is not supported on macOS due to missing ALPN support.)

対処:TLSを使わない

落ちる理由はエラーメッセージにも チュートリアル にも書いてあって、Macや古いWindowsではHTTP2 on TLSがサポートされていないからです。よってTLSを使わないようにすれば解決です。

で、.NET Core での gRPC のトラブルシューティング | Microsoft DocsにはProgram.csに書き足せという旨が書かれているわけですが、これが正直よくわからない。たぶんテンプレートの形式が変わってしまったのだろうなと思われます。

というわけで、次のようにして雑に解決しました。

Properties/launchSettings.json には

{
  "profiles": {
    "GrpcGreeter": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5142;https://localhost:7229",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

とありますが、これの applicationUrl からhttpsのほうのURLを削り、

{
  "profiles": {
    "GrpcGreeter": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": false,
      "applicationUrl": "http://localhost:5142",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

として保存します。

実行

これで実行できます。

$ dotnet run
ビルドしています...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5142
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /Users/suzusime/sandbox/GrpcGreeter/

grpcurlでテスト

これでサーバーが立つことがわかったので、grpcurlでAPIを叩いてみます。

reflectionを追加

grpcurlで叩くにはサーバーにreflection機能を追加する必要があるので、追加します(Goでやったときは不要だった気がするので本当は不要なのかも)。

まずは

$ dotnet add package Grpc.AspNetCore.Server.Reflection --version 2.40.0

でプロジェクトを追加します。

次に、Program.cs

using GrpcGreeter.Services;

var builder = WebApplication.CreateBuilder(args);

// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682

// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection(); // 追加

var app = builder.Build();

// Configure the HTTP request pipeline.
app.MapGrpcService<GreeterService>();
app.MapGrpcReflectionService(); // 追加
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");

app.Run();

のように編集します。

grpcurlのインストール

homebrewで入ります。

$ brew install grpcurl

grpcurlで叩く

サーバーを立てます。

$ dotnet run

別のコンソールを開いてgrpcurlでサーバーを叩きましょう。まずは describe でAPIの使い方を調べてみます。

# 機能の一覧を出す
$ grpcurl -plaintext localhost:5142 describe
greet.Greeter is a service:
service Greeter {
  rpc SayHello ( .greet.HelloRequest ) returns ( .greet.HelloReply );
}
grpc.reflection.v1alpha.ServerReflection is a service:
service ServerReflection {
  rpc ServerReflectionInfo ( stream .grpc.reflection.v1alpha.ServerReflectionRequest ) returns ( stream .grpc.reflection.v1alpha.ServerReflectionResponse );
}

# 型の詳細を見る
$ grpcurl -plaintext localhost:5142 describe greet.HelloRequest
greet.HelloRequest is a message:
message HelloRequest {
  string name = 1;
}

これでAPIの叩き方がわかったので、リクエストを送ってみます。

$ grpcurl -plaintext -d '{ "name": "世界" }' localhost:5142 greet.Greeter/SayHello
{
  "message": "Hello 世界"
}

gRPCのサーバーが動いていることが確かめられました。

その他

  • protobufのパスは GrpcGreeter.csproj で指定できるようになっています。protobufを変更しても、dotnet runしたときにいいかんじにC#のファイルも生成してくれるようです。
  • サーバーの実装は Services/GreeterService.cs にあります(見れば分かりますが)。Greeter.GreeterBaseという自動生成される基底クラスを継承してオーバーライドしていく方式みたいです。

所感

テンプレに従うだけで動かせるので、とりあえずgRPCを試してみたいという需要ならGoでやる以上に楽ですね。

あと、Visual Studio for Mac 2022 Previewも入れてみたのですが、重くて正直微妙でした。VS Codeの出来が良すぎる……。

ツイッターでシェア
みんなに共有、忘れないようにメモ

すずしめ

巫女見習いです。

Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。

また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!

有料記事を販売できるようになりました!

こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?

コメント