目录
概述
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::编译文件的输出路径,如果使用其它语言请使用对应语言的option
- --grpc_out:设定输出路径
- --plugin:设定编译需要的插件
- proto文件:需要编译的服务定义文件
编译成功后在输出目录会生成两个文件,然后添加到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查看远程调用结果:
远程服务调用成功!
项目源码:https://download.csdn.net/download/uiuan00/11945481
项目源码(含RPC流式方法):https://download.csdn.net/download/uiuan00/14068609