gRPC是什么?
用官网的一句话就是:A high-performance, open-source universal RPC framework。
要说gRPC,那就先说下什么的RPC框架,所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数一样。
而gRPC就是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架。gRPC使客户端和服务端应用程序可以透明地进行通信,并简化了连接系统的构建。它使用HTTP/2作为通信协议,使用 Protocol Buffers 作为序列化协议。
可能第一次看到这种通信框架比较陌生,介绍的也比较官方和抽象,这里说一下另一个常用的服务间通讯的方案,你可能就明白了,那就是RESTFul风格的API,想必每个人都用过RestfulAPI吧,这里就先简单说下RestfulAPI,如果这个还不是很理解的话,建议死记硬背。
1、REST,即Representational State Transfer的缩写。直接翻译的意思是"表现层状态转化"。 2、它是一种互联网应用程序的API设计理念:URL定位资源,用HTTP动词(GET,POST,DELETe,PUT,DETC)描述操作,比如只需要知道/api/blog,你就知道了他的常见的CURD多种操作。
3、简单来说就是url地址中只包含名词表示资源,使用http动词表示动作进行操作资源,将软件和网络这两个领域一定程度上结合起来。
4、之所以灵活,是因为他很少参与业务逻辑,只定义资源操作。 看完了RestfulAPI,你应该就能明白gRPC是干什么的了吧。
那两者有什么区别呢,平时在前后端分离或者移动端需要后端api的场景下,经常使用Restful丰富的API,既然大家已经习惯并熟悉了Restful,为何还用gRPC呢?
PS:下边的内容我基本是摘抄于官网和网络,文末有参考连接,今天主要是介绍下如何操作代码,文字讲解不是重点。
为什么要使用gRPC?
问题:既然是server/client模型,那么我们直接用restful api不是也可以满足吗,为什么还需要RPC呢?
我这里简单说明下优缺点和比较,说说到底使用gRPC有什么好处。
gRPC 和 Restful API
gRPC和Restful API都提供了一套通信机制,用于server/client模型通信,而且它们都使用http作为底层的传输协议(严格地说, gRPC使用的http2.0,而Restful api则不一定)。
不过gRPC还是有些特有的优势,如下:
1、gRPC可以通过protobuf来定义接口,从而可以有更加严格的接口约束条件。
2、通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。
3、gRPC可以方便地支持流式通信.
场景与好处
1、需要对接口进行严格约束的情况。
比如我们提供了一个公共的服务,很多人,甚至公司外部的人也可以访问这个服务,这时对于接口我们希望有更加严格的约束,我们不希望客户端给我们传递任意的数据,尤其是考虑到安全性的因素,我们通常需要对接口进行更加严格的约束。这时gRPC就可以通过protobuf来提供严格的接口约束。
2、对于性能有更高要求的轻量级微服务。
有时我们的服务需要传递大量的数据,而又不希望影响到我们的性能,这个时候也可以考虑gRPC服务,因为通过protobuf我们可以将数据压缩编码转化为二进制格式,通常传递的数据量要小得多,而且通过http2我们可以实现异步的请求,从而大大提高了通信效率。
同时,更适应于网络受限的环境,使用 Protocol Buffers二进制序列化消息,该序列化始终小于等效的JSON消息,对网络带宽需求比JSON小。
3、需要对接多种语言的微服务的情况。
比如我们公司的项目,有JAVA组,有Python组,或者.NETCore组别,每个组当然负责各自独立的子服务部分,那就需用用到不同语言之间的服务调用问题,不希望出现兼容性问题。这个时候就用到了gRPC了,它协定优先 API 开发,默认使用协议缓冲区,允许与语言无关的实现。可用于多种语言的工具,以生成强类型服务器和客户端。gRPC工具支持所有流行的开发语言,使gRPC成为多语言开发环境的理想选择。
4、需要处理流式处理请求或响应的点对点实时服务
gRPC用更小的网络带宽,又支持客户端、服务器和双向流式处理调用,更好的帮助处理流式请求。
(理论上通过http2.0就可以使用streaming模式, 但是通常web服务的Restful api似乎很少这么用,通常的流式数据应用如视频流,一般都会使用专门的协议如HLS,RTMP等,这些就不是我们通常web服务了,而是有专门的服务器应用。)
也并不是十全十美的
任何开发工具或者项目框架都不是十全十美的,就算是K8s、微服务或者DDD这么火热的技术也并不是无脑就上的,gRPC框架也有一定的弊端,或者至少是某些场景下是不适合的:
1、浏览器可访问的API。
浏览器不完全支持gRPC。虽然gRPC-Web可以提供浏览器支持,但是它有局限性,引入了服务器代理
2、广播实时通信
gRPC支持通过流进行实时通信,但不存在向已注册连接广播消息的概念
3、进程间通信
进程必须承载HTTP/2才能接受传入的gRPC调用,对于Windows,进程间通信管道是一种更快速的方法。
如何.NETCore上使用gRPC?
关于如何在ASP.NETCore上使用gRPC,这里有两种方法:
第一是直接创建gRPC模板项目(新建项目的时候直接新建grpc项目,然后开发接口)。
第二个就是在ASP.NETCore项目上创建gRPC服务(基于某个微服务新增grpc的功能)。都差不多
我这里就说第二种吧,因为我的项目都是创建好的微服务,然后需要新增grpc的通信功能
1、这是我的项目结构, .net5
就关注Cbf.Oscar.Client、Cbf.Oscar.ServiceInstance俩就行了
一会常用快捷键:鼠标光标点住需要引用的关键字上,alt+enter 选择提示引用命名空间
首先:Cbf.Oscar.ServiceInstance服务端安装nuget:Grpc.AspNetCore
2、然后新建protos文件夹放 proto文件;新建services文件夹放接口。
新增proto文件
3、编辑proto文件内容:
syntax = "proto3";
option csharp_namespace = "Cbf.Oscar.ServiceInstance";//项目程序集名称import "google/protobuf/empty.proto"; //需要使用空参数和空返回值时,需要使用这个默认的协议文件
package CBFOscar; //定义服务的包// The greeting service definition.
//service相当于定义一个接口
service CBFOscar {
// Sends a greeting
//google.protobuf.Empty
rpc getDetails(HelloRequest) returns (HelloReply);//当然如果有多个接口的话 都可以在下面定义
//rpc getDetails111(HelloRequest) returns (HelloReply);
//rpc getDetails222(HelloRequest) returns (HelloReply);
//rpc getDetails333(HelloRequest) returns (HelloReply);
}// The request message containing the user's name.
//传入参数
//message相当于定一个class类
message HelloRequest {
int32 Id=1;
}// The response message containing the greetings.
//返回结果
message HelloReply {
//repeated相当于定义一个集合
repeated UsersGRPC UsersGRPC= 1;
}message UsersGRPC
{
int32 Id = 1;
string LoginName= 2;
string UserName=3 ;
string PassWord=4 ;
string dateTime=5;
}
然后再做一个操作:
右键项目,编辑项目文件,可以看到有一个配置(没有的话则添加以下配置):
之后VSstudio会自动给我们创建生成服务、客户端和消息(表示传递的数据)的C# Class文件
编辑完之后保存就能生成文件(如果不行可以重新编译一下)。
生成的文件在项目下的 一个Protos文件夹下(自己可以找下看看是否生成):
4、proto文件弄完,接下来就是新建一个OscarService 类编写实现业务接口,如下:
using Cbf.Oscar.Interface;
using Cbf.Oscar.Model;
using Grpc.Core;
using System.Collections.Generic;
using System.Threading.Tasks;namespace Cbf.Oscar.ServiceInstance.Services
{
public class OscarService : CBFOscar.CBFOscarBase //CBFOscar.CBFOscarBase 就是根据proto生成的类文件
{
public IUsers _iusers;
public OscarService( IUsers iusers)
{
_iusers = iusers;
}///
/// getDetails就是实现了 CBFOscar.CBFOscarBase 中的接口(这些都是proto生成的类文件)
///
///
///
///
public override TaskgetDetails(HelloRequest request, ServerCallContext context)
{
Listm = _iusers.getUserList();//自己随便写的一个返回数据
HelloReply hello = new HelloReply(); //就是proto文件生成的那个返回结果
Listlist = new List (); //UsersGRPC 就是定义的那个集合类
foreach (var item in m) //填充数据
{
list.Add(new UsersGRPC()
{
Id = item.Id,
LoginName = item.LoginName,
UserName = item.UserName,
DateTime = item.dateTime.ToString("yyyy-MM-dd hh:mm:ss"),
});
}
hello.UsersGRPC.AddRange(list);//添加到UsersGRPC集合
return Task.FromResult(hello);//返回
}
}
}
注释都写明白了,特别简单的一个获取列表接口。
5、以上完成后我们要在服务端的startup中对grpc启用
注册一下我们刚才新建的接口类
6、最后一步也比较重要,因为grpc是http2协议,既然想调用需要配置一下appsettings.json
如果不改这个的话,一会演示客户端调用就会报错。当然,现在改了的话就不能通过浏览器直接访问了。
以上1-6 步骤是讲的服务端的搭建
7、下面是客户端的搭建:
我的客户端是.net5 mvc结构的项目
在Cbf.Oscar.Client 客户端nuget安装三个包:
Google.Protobuf
Grpc.Net.ClientFactory
Grpc.Tools
8、安装完后,把Protos文件夹和proto文件完全复制到客户端来
然后proto文件只需要改一下命名空间即可
option csharp_namespace = "Cbf.Oscar.Client";
9、还是右键项目,编辑项目文件,可以看到有一个配置(没有的话则添加以下配置):
之后VSstudio会自动给我们创建生成服务、客户端和消息(表示传递的数据)的C# Class类文件
10、以上完成后我们要在客户端的startup中对grpc注册
public void ConfigureServices(IServiceCollection services)
{//注册客户端,CBFOscar.CBFOscarClient是客户端生成的文件
services.AddGrpcClient();
}
11、最后的操作就是新建一个对外的接口进行访问,然后看看 grpc能不能访问到服务端的接口
我新建的是mvc的控制器,代码:
[Route("api/[controller]")]
public class HomeController : Controller
{
///
/// grpc测试
/// http://localhost:63210/api/Home/grpcMethod
/// 调试的时候别忘了服务端appsettings.json 开启http2
///
///
[HttpGet("grpcMethod")]
public string grpcMethod()
{
#region grpc
//允许http访问。但是我没用这个好像也能访问,奇怪。如果访问不通,请解开注释
//AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);var httphanlder = new HttpClientHandler();
httphanlder.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
//测试的时候使用,http 不加s,因为没证书
string url = "http://localhost:1000";//地址即可,grpc会根据 CBFOscar.getDetails找到对应的方法
HelloReply reply = null;
using (var channel = GrpcChannel.ForAddress(url, new GrpcChannelOptions { HttpHandler = httphanlder }))
{
var clients = new CBFOscar.CBFOscarClient(channel);//创建grpc请求
reply = clients.getDetails(new HelloRequest() { Id = 1 });//请求服务端grpc接口Console.WriteLine($"结果:{reply.UsersGRPC},message:{reply.UsersGRPC[0].Id}");
}
#endregion
return JsonConvert.SerializeObject(reply.UsersGRPC);
}
}
12、大功告成。先把服务端启动起来,然后启动客户端,可以自行走断点。
参考的学习资料:
.NET Core(.NET6)中gRPC使用_12107371的技术博客_51CTO博客
ASP.NET Core 使用 gRPC 初探 - 腾讯云开发者社区-腾讯云



