gRPCとREST:最高のAPIプロトコル入門
公開: 2022-07-22今日のテクノロジー環境では、ほとんどのプロジェクトでAPIを使用する必要があります。 APIは、単一の複雑なシステムを表す可能性があるが、別々のマシンに存在する場合や、互換性のない複数のネットワークまたは言語を使用する場合があるサービス間の通信をブリッジします。
多くの標準テクノロジーは、REST、SOAP、GraphQL、gRPCなどの分散システムのサービス間通信のニーズに対応しています。 RESTは好まれるアプローチですが、gRPCは価値のある候補であり、高性能、型付きコントラクト、および優れたツールを提供します。
RESTの概要
Representational State Transfer(REST)は、サービスのデータを取得または操作する手段です。 REST APIは通常、HTTPプロトコルに基づいて構築され、URIを使用してリソースを選択し、HTTP動詞(GET、PUT、POSTなど)を使用して目的の操作を選択します。 リクエストとレスポンスの本文には操作に固有のデータが含まれ、ヘッダーはメタデータを提供します。 説明のために、RESTAPIを介して製品を取得する簡単な例を見てみましょう。
ここでは、IDが11
の製品リソースをリクエストし、APIにJSON形式で応答するように指示します。
GET /products/11 HTTP/1.1 Accept: application/json
このリクエストを考えると、私たちの応答(無関係なヘッダーは省略)は次のようになります。
HTTP/1.1 200 OK Content-Type: application/json { id: 11, name: "Purple Bowtie", sku: "purbow", price: { amount: 100, currencyCode: "USD" } }
JSONは人間が読める形式ですが、サービス間で使用する場合は最適ではありません。 プロパティ名を参照することは、圧縮されている場合でも繰り返し発生するため、メッセージが肥大化する可能性があります。 この懸念に対処するための代替案を見てみましょう。
gRPCの概要
gRPC Remote Procedure Call(gRPC)は、オープンソースの契約ベースのクロスプラットフォーム通信プロトコルであり、一連の機能を外部クライアントに公開することにより、サービス間通信を簡素化および管理します。
HTTP / 2の上に構築されたgRPCは、双方向ストリーミングや組み込みのトランスポート層セキュリティ(TLS)などの機能を活用します。 gRPCは、シリアル化されたバイナリペイロードを介してより効率的な通信を可能にします。 RESTがJSONを使用するのと同様に、構造化データのシリアル化のメカニズムとしてデフォルトでプロトコルバッファを使用します。
ただし、JSONとは異なり、プロトコルバッファはシリアル化された形式以上のものです。 それらには、他の3つの主要な部分が含まれます。
-
.proto
ファイルにあるコントラクト定義言語(最新のプロトコルバッファ言語仕様であるproto3に従います)。 - 生成されたアクセサ機能コード
- 言語固有のランタイムライブラリ
サービスで使用できるリモート機能( .proto
ファイルで定義)は、プロトコルバッファファイルのサービスノード内に一覧表示されます。 開発者として、プロトコルバッファのリッチタイプシステムを使用して、これらの関数とそのパラメータを定義することができます。 このシステムは、入力メッセージと出力メッセージを定義するために、さまざまな数値と日付のタイプ、リスト、辞書、およびnullableをサポートしています。
これらのサービス定義は、サーバーとクライアントの両方で使用できる必要があります。 残念ながら、 .proto
ファイル自体への直接アクセスを提供する以外に、これらの定義を共有するデフォルトのメカニズムはありません。
この例の.proto
ファイルは、IDを指定して製品エントリを返す関数を定義しています。
proto3の厳密な型指定とフィールドの順序付けにより、メッセージの逆シリアル化はJSONの解析よりも大幅に負担が少なくなります。
RESTとgRPCの比較
要約すると、RESTとgRPCを比較する際の最も重要なポイントは次のとおりです。
休み | gRPC | |
---|---|---|
クロスプラットフォーム | はい | はい |
メッセージフォーマット | カスタムですが、通常はJSONまたはXML | プロトコルバッファ |
メッセージペイロードサイズ | 中/大 | 小さな |
処理の複雑さ | より高い(テキスト解析) | 低い(明確に定義されたバイナリ構造) |
ブラウザのサポート | はい(ネイティブ) | はい(gRPC-Web経由) |
それほど厳密ではないコントラクトとペイロードへの頻繁な追加が予想される場合は、JSONとRESTが最適です。 契約がより静的なままである傾向があり、速度が最も重要である場合、gRPCは一般的に勝ちます。 私が取り組んできたほとんどのプロジェクトで、gRPCはRESTよりも軽量でパフォーマンスが高いことが証明されています。
gRPCサービスの実装
合理化されたプロジェクトを構築して、gRPCを採用することがいかに簡単かを探りましょう。
APIプロジェクトの作成
開始するには、Visual Studio 2022 Community Edition(VS)で.NET6プロジェクトを作成します。 ASP.NET Core gRPCサービステンプレートを選択し、プロジェクト( InventoryAPI
を使用)とその中の最初のソリューション( Inventory
)の両方に名前を付けます。
それでは、を選択しましょう。 フレームワークのNET6.0(長期サポート)オプション:
製品サービスの定義
プロジェクトを作成したので、VSはGreeter
という名前のサンプルgRPCプロトタイプ定義サービスを表示します。 ニーズに合わせてGreeter
のコアファイルを再利用します。
- コントラクトを作成するために、
greet.proto
の内容をSnippet 1に置き換え、ファイルの名前をproduct.proto
に変更します。 - サービスを作成するために、
GreeterService.cs
ファイルの内容をSnippet 2に置き換え、ファイルの名前をProductCatalogService.cs
に変更します。
サービスはハードコードされた製品を返すようになりました。 サービスを機能させるには、 Program.cs
のサービス登録を変更して、新しいサービス名を参照するだけです。 この場合、 app.MapGrpcService<GreeterService>();
名前を変更します。 app.MapGrpcService<ProductCatalogService>();
新しいAPIを実行可能にします。
公正な警告:標準のプロトコルテストではありません
試してみたいと思うかもしれませんが、エンドポイントを対象としたブラウザーを介してgRPCサービスをテストすることはできません。 これを試みると、gRPCエンドポイントとの通信はgRPCクライアントを介して行われる必要があることを示すエラーメッセージが表示されます。
クライアントの作成
サービスをテストするために、VSの基本的なコンソールアプリテンプレートを使用して、APIを呼び出すgRPCクライアントを作成しましょう。 私はInventoryApp
という名前を付けました。
便宜上、契約を共有するための相対ファイルパスを参照しましょう。 参照を手動で.csproj
ファイルに追加します。 次に、パスを更新し、 Client
モードを設定します。 注:相対参照を使用する前に、ローカルフォルダー構造に精通し、自信を持っておくことをお勧めします。
サービスプロジェクトファイルとクライアントプロジェクトファイルの両方に表示される.proto
リファレンスは次のとおりです。
奉仕プロジェクトファイル (クライアントプロジェクトファイルにコピーするコード) | クライアントプロジェクトファイル (貼り付け編集後) |
---|---|
|
|
ここで、サービスを呼び出すために、 Program.cs
のコンテンツを置き換えます。 私たちのコードはいくつかの目的を達成します:
- サービスエンドポイントの場所を表すチャネルを作成します(ポートは異なる場合があるため、実際の値については、
launchsettings.json
ファイルを参照してください)。 - クライアントオブジェクトを作成します。
- 簡単なリクエストを作成します。
- リクエストを送信します。
ローンチの準備
コードをテストするには、VSでソリューションを右クリックし、[スタートアッププロジェクトの設定]を選択します。 [ソリューションプロパティページ]ダイアログで、次のことを行います。
- [複数のスタートアッププロジェクト]の横にあるラジオボタンを選択し、[アクション]ドロップダウンメニューで、両方のプロジェクト(
InventoryAPI
とInventoryApp
)を[開始]に設定します。 - [ OK]をクリックします。
これで、VSツールバーの[開始]をクリックして(またはF5キーを押して)ソリューションを開始できます。 2つの新しいコンソールウィンドウが表示されます。1つはサービスがリッスンしていることを示し、もう1つは取得した製品の詳細を示します。
gRPC契約共有
次に、別の方法を使用して、gRPCクライアントをサービスの定義に接続しましょう。 最もクライアントがアクセス可能な契約共有ソリューションは、URLを介して定義を利用できるようにすることです。 他のオプションは、非常に脆弱(パスを介してファイルを共有)するか、より多くの労力を必要とします(ネイティブパッケージを介して契約を共有)。 URLを介した共有(SOAPおよびSwagger / OpenAPIのように)は柔軟性があり、必要なコードが少なくて済みます。
開始するには、 .proto
ファイルを静的コンテンツとして利用できるようにします。 ビルドアクションのUIが「ProtobufCompiler」に設定されているため、コードを手動で更新します。 この変更により、コンパイラーは.proto
ファイルをコピーして、Webアドレスから提供できるようになります。 この設定がVSUIを介して変更された場合、ビルドは壊れます。 次に、最初のステップは、 InventoryAPI.csproj
ファイルにSnippet4を追加することです。
次に、 ProductCatalogService.cs
ファイルの先頭にあるSnippet 5にコードを挿入して、 .proto
ファイルを返すエンドポイントを設定します。
そして今、 app.Run()
の直前にSnippet6をProductCatalogService.cs
ファイルに追加します。
スニペット4〜6を追加すると、 .proto
ファイルの内容がブラウザに表示されます。
新しいテストクライアント
次に、VSの依存関係ウィザードを使用して既存のサーバーに接続する新しいコンソールクライアントを作成します。 問題は、このウィザードがHTTP/2を話さないことです。 したがって、HTTP / 1を介して通信し、サーバーを起動するようにサーバーを調整する必要があります。 サーバーが.proto
ファイルを利用できるようになったので、gRPCウィザードを介してサーバーにフックする新しいテストクライアントを構築できます。
- HTTP / 1を介して通信するようにサーバーを変更するには、
appsettings.json
ファイルを編集します。-
Protocol
フィールド(パスKestrel.EndpointDefaults.Protocols
にあります)を調整して、Https
を読み取ります。 - ファイルを保存します。
-
- 新しいクライアントがこの
proto
情報を読み取るには、サーバーが実行されている必要があります。 当初は、VSの[スタートアッププロジェクトの設定]ダイアログから以前のクライアントとサーバーの両方を起動していました。 サーバーソリューションを調整して、サーバープロジェクトのみを開始してから、ソリューションを開始します。 (HTTPバージョンを変更したため、古いクライアントはサーバーと通信できなくなりました。) - 次に、新しいテストクライアントを作成します。 VSの別のインスタンスを起動します。 「 APIプロジェクトの作成」セクションで説明されている手順を繰り返しますが、今回はコンソールアプリテンプレートを選択します。 プロジェクトとソリューションに
InventoryAppConnected
という名前を付けます。 - クライアントシャーシを作成したら、gRPCサーバーに接続します。 VSSolutionExplorerで新しいプロジェクトを展開します。
- [依存関係]を右クリックし、コンテキストメニューで[接続されたサービスの管理]を選択します。
- [接続されたサービス]タブで、[サービス参照の追加]をクリックし、[ gRPC ]を選択します。
- [サービス参照の追加]ダイアログで、 URLオプションを選択し、サービスアドレスの
http
バージョンを入力します(launchsettings.json
からランダムに生成されたポート番号を取得することを忘れないでください) 。 - [完了]をクリックして、簡単に保守できるサービス参照を追加します。
この例のサンプルコードに対して、自由に作業を確認してください。 内部的には、VSは最初のテストで使用したものと同じクライアントを生成したため、前のサービスのProgram.cs
ファイルの内容をそのまま再利用できます。
コントラクトを変更するときは、更新された.proto
定義に一致するようにクライアントのgRPC定義を変更する必要があります。 そのためには、VSの接続サービスにアクセスし、関連するサービスエントリを更新するだけで済みます。 これでgRPCプロジェクトが完了し、サービスとクライアントの同期を簡単に保つことができます。
あなたの次のプロジェクト候補:gRPC
私たちのgRPC実装は、gRPCを使用する利点を直接垣間見ることができます。 RESTとgRPCにはそれぞれ、契約の種類に応じて独自の理想的なユースケースがあります。 ただし、両方のオプションが当てはまる場合は、gRPCを試してみることをお勧めします。これにより、APIの将来の時代を先取りすることができます。