目錄
概述
gRPC 是一個高性能、開源和通用的 RPC 框架,面向移動和 HTTP/2 設計。目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
gRPC 基於 HTTP/2 標準設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多複用請求等特。這些特性使得其在移動設備上表現更好,更省電和節省空間佔用。
gRPC 一開始由 google 開發,是一款語言中立、平臺中立、開源的遠程過程調用(RPC)系統。
所謂RPC(remote procedure call 遠程過程調用)框架實際是提供了一套機制,使得應用程序之間可以進行通信,而且也遵從server/client模型。使用的時候客戶端調用server端提供的接口就像是調用本地的函數一樣。如下圖所示就是一個典型的RPC結構圖。
使用場景
- 需要對接口進行嚴格約束的情況,比如我們提供了一個公共的服務,很多人,甚至公司外部的人也可以訪問這個服務,這時對於接口我們希望有更加嚴格的約束,我們不希望客戶端給我們傳遞任意的數據,尤其是考慮到安全性的因素,我們通常需要對接口進行更加嚴格的約束。這時gRPC就可以通過protobuf來提供嚴格的接口約束。
- 對於性能有更高的要求時。有時我們的服務需要傳遞大量的數據,而又希望不影響我們的性能,這個時候也可以考慮gRPC服務,因爲通過protobuf我們可以將數據壓縮編碼轉化爲二進制格式,通常傳遞的數據量要小得多,而且通過http2我們可以實現異步的請求,從而大大提高了通信效率。
gRpc使用示例
gRPC的使用通常包括如下幾個步驟:
- 通過Protocol Buffer來定義接口和數據類型
- 通過Protocol Buffer編譯器編譯proto文件爲對應平臺的代碼文件
- 編寫gRPC server端代碼
- 編寫gRPC client端代碼
下面以C#爲例介紹gRpc的使用流程:
創建解決方案
分別新建gRpcDemo C#類庫,gRpcService、gRpcClient控制檯應用程序,項目結構如下:
項目gRpcDemo中包含.proto文件及protocol buffer 生成文件,生成C#代碼文件可在gRpcService和gRpcClient中訪問對應接口及服務代碼實現。本示例服務端和客戶端採用相同的語言,如果平臺語言一致需要分別生成對應的代碼文件到項目中。
定義.proto文件
定義文件LogService.proto文件(文本文件直接編輯在更改文件名)
syntax = "proto3"; //指定語法proto2或proto3 本文采用proto3
//package gRpcDemo; //指定命名空間
option csharp_namespace = "gRpcDemo";
//定義rpc服務
service gRpcQueryService
{
rpc Search(QureyCond) returns (QueryResult);
}
//定義查詢條件消息體
message QureyCond
{
int32 id=1; //通過id查詢
}
//定義查詢結果實體對象
message QueryResult
{
int32 id=1;
string name=2;
int32 age=3;
}
proto文件編譯
添加工具包
右鍵點擊“解決方案gRpc”,點擊“管理解決方案的NuGet程序包”,在瀏覽中分別搜索"Grpc"、"Grpc.Tools"、"Google.Protobuf",然後點擊右面項目,全選,再點擊安裝
編譯proto文件
在項目packages文件夾(*\packages\grpc.tools\2.25.0-pre1\tools\windows_x64)下找到protoc.exe和grpc_csharp_plugin.exe(如果項目文件夾下沒有packages就新建,並將上面找到的.nuget\packages中的“Google.protobuf”、“grpc”、“grpc.tools”文件夾拷貝到我們工程文件夾下的packages裏面)。
在dos下使用proto編譯器執行命令:
- -I:設定源路徑
- --csharp_out::第一個參數設定編譯文件的路徑,第二個參數設定需要編譯的proto文件;如果使用其它語言請使用對應語言的option
- --grpc_out:設定輸出路徑
- --plugin:設定編譯需要的插件
編譯成功後在輸出目錄會生成兩個文件,然後添加到gRpcDemo項目中:
完成後編譯gRpcDemo類庫,然後添加項目引用到gRpcService和gRpcClient中。
實現服務代碼
在項目gRpcServer項目中實現服務邏輯:
namespace gRpcServer
{
class Program
{
const int Port = 8050;
public static void Main(string[] args)
{
Server server = new Server
{
Services = { gRpcQueryService.BindService(new GRPCImpl()) },
Ports = { new ServerPort("localhost", Port, ServerCredentials.Insecure) }
};
server.Start();
Console.WriteLine("gRPC server listening on port " + Port);
Console.WriteLine("任意鍵退出...");
Console.ReadKey();
server.ShutdownAsync().Wait();
}
}
class GRPCImpl :gRpcQueryService.gRpcQueryServiceBase
{
public override Task<QueryResult> Search(QureyCond request, ServerCallContext context)
{
return Task.FromResult(Search(request));
}
private QueryResult Search(QureyCond cond)
{
//自定義邏輯
QueryResult result = new QueryResult();
result.Id = cond.Id;
result.Name = "張三";
result.Age = 20;
return result;
}
}
}
調用遠程服務
在項目gRpcClient項目中實現調用服務邏輯:
namespace gRpcClient
{
class Program
{
static void Main(string[] args)
{
Channel channel = new Channel("127.0.0.1:8050", ChannelCredentials.Insecure);
var client = new gRpcQueryService.gRpcQueryServiceClient(channel);
var result = client.Search(new QureyCond { Id = 2 });
Console.WriteLine("結果:id={0} name={1} age={2}", result.Id, result.Name, result.Age);
channel.ShutdownAsync().Wait();
Console.WriteLine("任意鍵退出...");
Console.ReadKey();
}
}
}
RPC遠程調用測試
分別運行gRpcServer和gRpcClient查看遠程調用結果:
遠程服務調用成功!