GrpcをC#で実装するには
必要なNuGetパッケージ
Google.Protobuf
→やれることは以下のURLを参照
https://kagasu.hatenablog.com/entry/2018/04/29/233407#1-NuGet%E3%81%8B%E3%82%89-GoogleProtobuf-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B
今回は作成したprotoファイルを使うことに使用
Grpc
→Grpcを使用するためのライブラリ
Grpc.Reflection
Grpc.Tools
→Grpcで使用するファイル等を自動生成してくれるライブラリ
ビルドを実行することで自動生成される
Grpc環境の作成については以下のURLを参照
https://qiita.com/muroon/items/4e12dde47b9e8b1e94d3
前準備が完了したら、Grpcの実装を行っていく。
1.protoファイルの作成
下記が書き方の一例
syntax = "proto3";
package Grpctst;
service GrpcTest{
rpc TestRun (TestRequest) returns (TestResponse) {}
}
message TestRequest{
string request = 1;
}
message TestResponse {
string response = 1;
}
上記のファイルの意味
syntax:決まり文句みたいなもの
package:対象のnamespaceみたいなもの
service サービス名:サービスの名前とメソッドの定義引数と戻りを定義できる。
message メッセージ名:引数や戻り値の情報を定義する箇所
stringやintなどの型を定義する。
1は割り当てているIDみたいなものである。
複数記載することも可能。
2.protoファイルの作成が完了後は、クラスライブラリMicrosoft.NET.Sdkを作成する。
作成後はプロジェクトのソリューションの設定に以下を追加する。
3.追加後にビルドを実行する。
実行するとクラスファイルを自動生成してくれる。
Grpctst.cs
GrpctstGrpc.cs
が生成されていればOK(ファイル名はパッケージ名いよって異なる)
これでGrpc操作を行う環境設定については完了。
4.データ受信の方法
受信を行うために以下のファイルを作成する。
GrpcTestImpl.cs(protoファイルのメソッドを設定するクラス)
GrpcTestReceive.cs(Grpcとやりとりをするためのクラス)
GrpcTestImpl.cs
class GrpcTestImpl : GrpcTest.GrpcTestBase
{
public override Task TestRun(TestRequest request, ServerCallContext context)
{
return Task.FromResult(new TestResponse { Response = request.request });
}
}
上記はGrpcTest.GrpcTestBaseを継承しています。
GrpcTestBaseは自動生成されたGrpctstGrpc.csの中で実装されています。
TestRunメソッドをオーバーライドして処理を記載することができます。
今回はテストですので、受信してきたデータをreturnするだけの処理としています。
GrpcTestReceive.cs(ほとんど決まり文句)
public class GrpcTestReceive
{
const int Port = 50051;
public void Run()
{
Server server = new Server
{
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
};
var grpcTest = GrpcTest
.BindService(new GrpcTestImpl())
.Intercept(new GrpcInterceptor());
server.Services.Add(grpcTest);
var reflectionService = ServerReflection
.BindService(new ReflectionServiceImpl(GrpcTest.Descriptor))
.Intercept(new GrpcInterceptor());
server.Services.Add(reflectionService);
server.Start();
}
public class GrpcInterceptor : Interceptor
{
public override Task<TResponse> ClientStreamingServerHandler<TRequest, TResponse>(
IAsyncStreamReader<TRequest> requestStream
, ServerCallContext context
, ClientStreamingServerMethod<TRequest, TResponse> continuation
)
{
return base.ClientStreamingServerHandler(requestStream, context, continuation);
}
public override Task DuplexStreamingServerHandler<TRequest, TResponse>(
IAsyncStreamReader<TRequest> requestStream
, IServerStreamWriter<TResponse> responseStream
, ServerCallContext context
, DuplexStreamingServerMethod<TRequest, TResponse> continuation
)
{
return base.DuplexStreamingServerHandler(requestStream, responseStream, context, continuation);
}
public override Task ServerStreamingServerHandler<TRequest, TResponse>(
TRequest request
, IServerStreamWriter<TResponse> responseStream
, ServerCallContext context
, ServerStreamingServerMethod<TRequest, TResponse> continuation
)
{
return base.ServerStreamingServerHandler(request, responseStream, context, continuation);
}
public override Task<TResponse> UnaryServerHandler<TRequest, TResponse>(
TRequest request
, ServerCallContext context
, UnaryServerMethod<TRequest, TResponse> continuation
)
{
foreach (var header in context.RequestHeaders)
{
Console.WriteLine(header);
}
var tokenHeader = context.RequestHeaders.FirstOrDefault((entry) => entry.Key == "token");
if (tokenHeader == null)
{
context.Status = new Status(StatusCode.Unauthenticated, "ヘッダーにトークン情報がありません.");
}
return base.UnaryServerHandler(request, context, continuation);
}
}
5.各種クラスの設定が完了したら実装は完了です。
実装が完了したらテストを行ってみる。
テストを行うのに便利なcurlツールでgrpcurlというのがあるので、使用してみるといいかもしれません。
インストールから使い方については以下を参照。
https://qiita.com/yukina-ge/items/a84693f01f3f0edba482
grpccurlのコマンド一例
サービス一覧表示
grpcurl -plaintext localhost:50051 list
サービス内のメソッド一覧を表示
grpcurl -plaintext localhost:50051 list サービス一覧表示で取得した名称
サービス呼び出し
grpcurl -plaintext localhost:50051 サービス一覧表示で取得した名称/サービス内のメソッド名称