「ソフテックだより」では、ソフトウェア開発に関する情報や開発現場における社員の取り組みなどを定期的にお知らせしています。
さまざまなテーマを取り上げていますので、他のソフテックだよりも、ぜひご覧下さい。
ソフテックだより(発行日順)のページへ
ソフテックだより 技術レポート(技術分野別)のページへ
ソフテックだより 現場の声(シーン別)のページへ
「ソフテックだより」では、みなさまのご意見・ご感想を募集しています。ぜひみなさまの声をお聞かせください。
近年まで、.NETアプリケーション同士の通信にはWCF(Windows Communication Foundation)が広く使われてきました。
WCF は、サービス指向アプリケーションを構築するためのフレームワークです。
WCFを利用した通信では、あるサービスエンドポイントから別のサービスエンドポイントに非同期メッセージとしてデータを送信できます。
このメッセージはXML形式で表現され、実際には「単一の文字」「単語」と同じくらいシンプルなものです。
WCFは多様な通信プロトコルに対応し、柔軟な設計が可能なフレームワークですが、一方で設定の複雑さやWindows依存やXMLベース通信によるパフォーマンスの限界などの課題もありました。
そのような背景の中で登場したのがgRPC(Google Remote Procedure Call)です。
Googleが開発したgRPCは、軽量・高速・クロスプラットフォーム対応の通信技術です。
HTTP/2とProtocol BuffersをベースとしたgRPCでは、WCFのような複雑な設定をせずに通信を行うことができます。
本記事では、gRPCの特徴やメリット・デメリットを紹介し、サンプルのアプリケーションを用いてgRPCの実装方法について解説します。
gRPCは、Googleが開発した高性能なリモートプロシージャコール(RPC)フレームワークで、離れたコンピューター同士がまるで関数を呼び出すように通信できる仕組みを提供します。
オープンソースとして公開されており、誰でもコードを閲覧・利用・カスタマイズすることが可能です。
また、C#、Java、Pythonなど多くのプログラミング言語に対応しており、クロスプラットフォーム環境でも柔軟に利用できます。
gRPCの通信には、Googleが開発したProtocol Buffersというバイナリ形式が使われており、XMLなどのテキスト形式に比べてデータがコンパクトで処理が高速です。
これにより、通信の負荷が軽減され、軽量かつ効率的なデータのやり取りが可能になります。
さらに、通信はHTTP/2をベースとしており、多重化やストリーミングなどの機能を活用することで、より高速で安定した通信が実現されています。
開発者は、通信の要求と応答を.protoファイルで定義することで、必要なコードを自動生成できるため、複雑な通信処理を手書きする必要がありません。
上記の特徴を踏まえ、gRPCを利用することで得られるメリットと注意すべきデメリットについて紹介します。
vgRPCを実装するにあたって事前に以下の準備が必要です。
本章では、これらの準備についてサンプルのプロジェクトを用いて順を追って説明します。構成図は下記の通りです。

図1. 構成図
また使用言語、開発環境は下記の通りです。
・言語:C#
・開発環境:.NET 8.0
gRPCサービスを利用する場合、クライアントアプリとサーバーアプリで同一の.protoファイルを共有する必要があります。
.protoファイルにはバージョンの定義やRPCメソッドなどを記述します。.protoファイルで定義できるデータ型は下記の表のとおりです。
表1. .protoファイルで定義可能なデータ型
| データ型 | デフォルト値 | 補足 |
|---|---|---|
| string | 空文字 | |
| bytes | 空配列 | |
| bool | False | |
| 数値(int, floatなど) | 0 | |
| enum | 最初に定義された値 | |
| message | null | データ構造を定義するための基本単位。 入れ子構造にして定義することも可能 |
| repeated | 空配列 | リストとして定義することが可能。 |
.protoファイルのサンプルは下記の通りです。
・.protoファイルのサンプル
syntax = "proto3";
option csharp_namespace = "MessageService";
// -------------------------------------------------------------
// RPCメソッド定義
service MessageService {
// 挨拶取得
rpc SendMessageResponse(Request_Message) returns (Response_Message);
}
// -------------------------------------------------------------
// 挨拶リクエストメッセージ
// 要求種別コード
enum RequestCode{
Morning = 0;
Afternoon = 1;
Evening = 2;
}
// 挨拶リクエストメッセージ
message Request_Message{
// 要求種別コード
RequestCode Req_Code = 1;
}
// -------------------------------------------------------------
// 挨拶レスポンスメッセージ
message Response_Message{
// 挨拶メッセージ
string Res_Message = 1;
}
サーバーとなるアプリの設定はパッケージのインストール、.protoファイルの設定、サーバーコードの作成の3点を行います。
NuGetで下記の3つのパッケージをインストールします。
Protosフォルダを.csprojファイルと同階層に作成し、このフォルダ内に3-1で作成した.protoファイルを格納します。
その後、.csprojファイルに下記のコードを記述し、.protoファイルの定義を追加します。
・サーバーアプリ .csprojファイル追記コード
<ItemGroup>
<Protobuf Include=”Protos\*.proto” GrpcServices=”Server” />
</ItemGroup>
gRPC通信では、サーバーアプリがクライアントからのリクエストを受け取り、指定された処理を実行して結果を返します。 .protoファイルの定義をもとに、サーバー側のコードが自動生成されるため、このコードを使って簡単に通信処理を記述できます。
・サーバーコード(クラス実装)
// 自動生成されたクラスを継承して、サーバー側処理内容を実装
public class ServiceIF : MessageService.MessageServiceBase
{
public override Task<Response_Message> SendMessageResponse(Request_Message request, ServerCallContext context)
{
// 処理結果の生成
var response = new Response_Message();
if (request.ReqCode == RequestCode.Morning)
{
response.ResMessage = "Good Morning!";
}
else if (request.ReqCode == RequestCode.Afternoon)
{
response.ResMessage = "Good Afternoon!";
}
else if (request.ReqCode == RequestCode.Evening)
{
response.ResMessage = "Good Evening!";
}
// クライアントへ応答送信
return Task.FromResult(response);
}
}
・サーバーコード(インスタンスの初期化)
// サービス処理インスタンス作成
gRPC_Server = new Server()
{
Services = { MessageService.BindService(new ServiceIF()) },
Ports = { new ServerPort("127.0.0.1", 30001, ServerCredentials.Insecure) }
};
// サービス処理開始
gRPC_Server.Start();
クライアントとなるアプリではパッケージのインストールと.protoファイルの設定、クライアントコードの作成を行います。
サーバーアプリと同様に、NuGetで下記の3つのパッケージをインストールします。
こちらもサーバーアプリと同様に、Protosフォルダを.csprojファイルと同階層に作成し、このフォルダ内に3-1で作成した.protoファイルを格納します。その後、.csprojファイルに下記のコードを記述し、.protoファイルの定義を追加します。
・クライアントアプリ .csprojファイル追記コード
<ItemGroup>
<Protobuf Include=”Protos\*.proto” GrpcServices=”Client” />
</ItemGroup>
gRPCでは通信仕様を.protoで定義します。クライアントアプリもサーバーアプリと同様にこのファイルをもとに、クライアント側のコードが自動生成されるため、このコードを使って簡単に通信処理を記述できます。
・クライアントコード
// gRPCインスタンス作成
gRPC_Channel = new Grpc.Core.Channel( _IPAddress, _PortNumber, ChannelCredentials.Insecure);
gRPC_Client = new MessageService.MessageService.MessageServiceClient(gRPC_Channel);
// 要求データ作成
Request_Message req = new Request_Message();
req. Req_Code = RequestCode.Morning;
// gRPCメソッド 呼び出し
Response_Message res = gRPC_Client. SendMessageResponse();
gRPCは、異なるプラットフォームやアプリケーション間で効率的かつ高速に通信できる仕組みであり、現代のシステム開発において非常に有用です。基本的な構成や使い方を理解すれば、アプリケーション開発にとても役立ちます。ただしgRPCの導入を検討する際は既存のシステム構成や通信要件を踏まえて選定することが重要です。
今回のgRPCの基本的な仕組みやメリット・デメリットの紹介を通して、プロジェクトに合った技術選定の一助になれば幸いです。
(R.K.)
関連ページへのリンク
関連するソフテックだより
「ソフテックだより」では、みなさまのご意見・ご感想を募集しています。ぜひみなさまの声をお聞かせください。