74. gRPC on ASP.NET Core を試す
はじめに
数回、WCF を試してきました。WCF がリリースされてしばらくは、Windows 系でサービス指向アプリケーションを開発するデファクトだったのですが、今や、一昔前の技術セットになっているようです。Microsoft Learn のドキュメントにも
とあるように、gRPC の方が今時らしい。
…ということで、IoT 系のサービス API でもよく見かけるようになった gRPC を試すことにします。
そしてしつこく、クライアント側でのアクセスを WCF のツールでやってみます。
gRPC とは
Wikipedia によれば、
だそうで、
クロスプラットフォーム
オープンソース
ハイパフォーマンス
な、HTTP/2 ベースのRemote Procedure Call(略して RPC ってこと)のフレームワークとのことで、スケーラブルなマイクロサービス間通信で威力を発揮するとのことです。最初の”g”は、Google ですかね。2015年に開発されているので比較的新しいフレームワークです。2015年といえば、私はマイクロソフトで既に IoT の普及啓発活動を始めてましたね。IoT が一番バズワード化していた最盛期…懐かしい!
サーバー・クライアント開発方法
gRPC はじめからていねいに #初心者 - Qiita に gRPC のサーバー・クライアントのアーキテクチャ、作り方の基本が説明されています。Python で簡単に開発できるようです。Google 由来なので、当然 Go でも作れるようです。gRPCサーバー開発入門 #Go - Qiita この辺に書いてありました。
今回は、ASP.NET Core で C# によるサーバー側の開発を行うのですが、何故このチョイスかというと、単に、WCF のサーバー参照に gRPC があり、プロジェクトテンプレートに、ASP.NET Core の gRPC 開発向けのものがあったからという単純な理由です。Python や Go なら他の人たちが山ほど書いてるしね。
そもそも RPC って何?
gRPC という名前は、Google の(多分)Remote Procedure Call ということですが、そもそも RPC が何かということも簡単に書いておきますね。ここでの説明はあくまでも私の私的な説明であることをあらかじめ宣言しておきます。ご容赦ください。
Remote Procedure Call は、あるノード上で公開されている手続き(Procedure)を、別のノードから(Remote)関数形式で Call するための仕組みです。
UNIX の登場以来、スレッドというライトウェイトな仕組みが登場する前から、コンピュータ上でプログラムが実行される単位はプロセスでした。ひとつのプロセスは、独自の独立したコールスタックとメモリ領域を持ちます。あるプロセスから、別のプロセスのメモリ領域を参照することはできないし、別のプロセス上で動いているプログラムの関数をコールすることもできません。プロセスを複数実行可能な OS のことをマルチプロセス対応 OS と呼んだりもします。
現代の OS は超小型機器向けを除いて、ほとんどがマルチプロセス対応 OS です。Linux は UNIX の後継なので最初からマルチプロセス対応でしたが、MS-DOS、Windows 3.1、Windows XPなどはシングルプロセス OS で(じゃぁ当時の Windows がどうやって複数アプリケーションを同時に実行していたかその仕組みも結構面白いですよ。最初のうちはスレッドすらなかったのだから)、マルチプロセス OS になったのは、Windows 95 から(Windows NT 4.0がマルチプロセスOSではない:by Copilot:というのは結構意外)のようです。
話をプロセスに戻します。あまり関係のない仕事をコンピュータにさせたい場合、マルチプロセス OS なら、それぞれの仕事をプログラム化して複数のプロセスで実行すれば効率的です。最も、昔々のシングルコア(一つのコア:一つのコアが処理を実行)しかもっていない CPU がたった一つで動いているコンピュータなら、何らかの優先順位に従って、プロセスをスケジューリングして細切れにどれか一つのプロセスが実行され、実行されるプロセスを切り替えながら、見かけ上複数のプロセスが動いているような環境でした。プロセスを切り替えるたびにメモリ上には、それぞれのプロセスごとのメモリ領域がロードされて動くことになります。技術が進化し、マルチプロセッサ(CPU)搭載だったり、マルチコア(複数のコア)の CPU が登場してきました。こうなると、ある分だけのコアにプロセスを割り当てることができて、見かけ上ではなく、実際に複数のプロセスを同時並行的に実行することができるようになりました。
一つのまとまった仕事を遂行するにしても、コンピュータ上の実行にある程度の時間を有する有限リソース(UI やファイルシステム、HWアクセラレータ等)の利用や、時間がかかる計算処理などを含む場合は、データーフロー的な依存関係で本来なら同時並行的に処理可能な内容(詳しくは”Essence of Software Design”を読んでね)も、(あくまでもマルチスレッドでない場合)、ただ一つだけのプロセスでの実行では、時間がかかる処理が終了するまで、あるいは、他のプロセスがリソースを手放すまで、別の処理を行うことができません。なので、一つのまとまった仕事を実装する場合でも、複数プロセスに分割して同時並行的に実行するアーキテクチャが重要になってきます。また、このようにデータの観点で分割して切り出された作業単位は、別の仕事でも利用可能なケースも多いので、複数の仕事を遂行するプログラムを構築する際の再利用可能部品にもなりえることになり、良いことずくめです。
加えて、複数のプロセスは同じコンピュータノード上にあっても良いし、ネットワークで接続された別のコンピュータノード上に配置することも可能です。このようなシステムを分散システムと呼びます。あるコンピュータノードが HW 的に故障した場合などは、代替のコンピュータノードに必要なプロセスを配置すれば可溶性は増すし、処理量が増えれば、コンピュータノードを増やすことによるスケーラビリティを実現することも可能になります。
しかし、一つの仕事を複数のプロセスに分割すると、ただ一つだけのプロセスで動くプログラムの実装であれば、普通に使えた関数コールが利用できません。プロセス間同士では互いのメモリ領域はアクセスできないので、通常の引数と戻り値を伴うような関数コールの代替として、UNIX 時代からの伝統的な Socket や Pipe というインタープロセス通信機構を使うことになります。この機構を使う場合、基本的にはバイト列のメッセージのやり取りしかできません。利用する側のプロセス(クライアントと呼ぶ)では、関数コールでは一行で済んだコーディングが、
利用したい関数名と引数をバイト列化
こういう処理を”シリアライズ”と呼ぶ
インタープロセス通信機構を使って別プロセスと通信するためのチャネルを開く
開いたチャネルでバイト列化したデータを別プロセスに送信
別プロセスから送られてきたバイト列を戻り値に復元
こういう処理を”デシリアライズ”と呼ぶ
不要になったらチャネルを閉じる
というコーディングになってしまいます。また、別プロセス(サーバーと呼ぶ)側でも、
ここから先は
Azure の最新機能で IoT を改めてやってみる
2022年3月にマイクロソフトの中の人から外の人になった Embedded D. George が、現時点で持っている知識に加えて、頻繁に…
この記事が気に入ったらチップで応援してみませんか?