小工具知识网

当前位置: 首页 > 行业知识 > gRPC知识归档

行业知识

gRPC知识归档

2026-11-06 19:50:43 来源:互联网转载

文章目录

  • gRPC知识归档
    • gRPC原理
      • 什么是gRPC
      • gRPC的特性
      • gRPC支持语言
      • gRPC使用场景
      • gRPC设计的动机和原则
      • 数据封装和数据传输问题
        • 网络传输中的内容封装和数据体积问题
        • JSON
        • Protobuf(微服务之间的服务器调用,一般采用二进制序列化,比如protobuf)
        • 网络传输效率问题
        • gRPC的4种模式
          • 一元RPC模式
          • 服务端流RPC模式
          • 客户端流RPC
          • 双向流RPC模式
          • gRPC同步异步
            • gRPC调用关系图
            • proto文件
            • Client
            • server
            • 异步相关概念
              • 异步Client
              • 异步Server
              • 关���图

                gRPC知识归档

                gRPC原理

                什么是gRPC

                RPC是远程调用协议(Remote Procedure Call Protocol),可以让我们像调用本地对象一样发起远程调用。RPC凭借强大的治理功能,成为解决分布式系统问题的一大利器。

                gRPC是一个现代的,高性能的,开源的和语言无关的通用RPC框架,HTTP2协议设计,序列化使用PB(Protocol Buffer)高性能序列化框架,基于HTTP2+PB保证高性能。

                gRPC的Server和Client工作流程大致如下:

                • tars兼容grpc
                • brpc也兼容grpc
                • grpc不兼容tars和brpc

                  gRPC的特性

                  1. gRPC基于服务的思想:定义一个服务,描述这个服务的方法和出入参数,服务端有这个服务的具体实现,客户端保有一个存根,提供与服务端相同的服务。
                  2. gRPC默认采用protobuf作为IDL(Interface Description)接口描述语言,服务之间通信数据序列化和反序列化也是基于protocol buffer的,因为protocol buffer的特殊性,所以gRPC框架是跨语言的通信框架,可就是说用jave开发的gRPC服务,可以用GoLang,C++等语言调用。
                  3. gRPC同时支持同步和异步调用,同步RPC调用会一直阻塞到服务端处完成返回数据,异步RPC是客户端调用服务端时不等待服务端处理完成返回结果,而是服务端处理完成后主动回调客户端高速客户端处理完成。
                  4. gRPC是基于HTTP2.0协议实现的,http2提供了很多新特性,并且在性能上相比http1提高了许多,所以gRPC的性能是非常好的。
                  5. gRPC并没有直接实现负载均衡和服务发现的功能,但是已经提供了自己的设计思路。已经为命名解析和负载均衡提供了接口。
                  6. 基于http2的协议特性,gRPC允许自定义4类服务方法
                    • 一元RPC
                    • 服务端流式RPC
                    • 客户端流式RPC
                    • 双向流式RPC

                  gRPC支持语言

                  C++,Java(包括安卓),OC,Python,Ruby,Go,C#,Node.js。

                  gRPC使用场景

                  1. 低延迟,高可扩展性的分布式系统
                  2. 开发与云服务器的客户端
                  3. 设计一个准确,高效,与语言无关的新协议
                  4. 分层设计,实现扩展,例如:身份验证,负载平衡,日志记录和监控。

                  gRPC设计的动机和原则

                  1. 自由,开放:所有人,所有平台都可以使用,开源,跨平台,跨语言
                  2. 协议可插拔:不同的服务需要使用不同的消息类型和编码机制,例如,JSON,XML和Thirft,所以协议应允许可插拔机制,还有负载均衡,日志,监控等都支持可插拔机制。
                  3. 阻塞和非阻塞:支持客户端和服务器交换的消息序列的异步和同步处理。
                  4. 取消和超时:一次RPC操作可能是持久并且昂贵的,应该允许客户设置取消RPC通信和对这次通信加上超时时间。
                  5. 拒绝:必须允许服务器通过在继续处理请求的同时拒绝新请求的到来并且优雅地关闭
                  6. 流处理:存储系统依靠流和流控制来表达大型数据集,其他服务,如语音到文本或者股票行情,依赖流来表达与时间相关的消息序列。
                  7. 流控制:计算能力和网络容量在客户端和服务器之间通常是不平衡的。流控制允许更好的缓冲区管理,以及过度活跃的对等提供DOS保护。
                  8. 元数据交换:认证或跟踪常见的跨领域问题依赖于不属于服务器的接口数据交换。依赖他们的将这些特性演进到服务,暴露API来提供能力。
                  9. 标准化状态骂:客户端通常以有限的方式相应API调用返回的错误。应约束状态码名称空间,以使这些错误处理决策更加清晰。如果需要更加丰富的特定领域的状态,则可以使用元数据交换机制来提供状态。
                  10. 互通性:报文协议必须遵循普通互联网服务基础框架

                  数据封装和数据传输问题

                  网络传输中的内容封装和数据体积问题

                  早期的RPCJSON的方式,目前的RPC基本上都采用类似的Protobuf的二进制序列化方式。

                  其差别在于:json的设计是给人看的,protobuf的设计是给机器看的

                  JSON

                  优点:在body中对JSON内容编码,极易跨语言,不需要约定特定的复杂编码格式和Stub文件。在版本兼容性上很好,扩展容易。

                  缺点:JSON难以表达复杂的参数类型,如结构体等;数据冗余和低压缩率使得传输特性能差。

                  Protobuf(微服务之间的服务器调用,一般采用二进制序列化,比如protobuf)

                  // XXXX.proto// rpc服务的类 service关键字, Test服务类名service Test {// rpc 关键字,rpc的接口rpc HowRpcDefine (Request) returns (Response) ; // 定义一个RPC方法}// message 类,c++ classmessage Request {//类型 | 字段名字| 标号int64 user_id = 1;string name = 2;}message Response {repeated int64 ids = 1; // repeated 表示数组Value info = 2; // 可嵌套对象map values = 3; // 可输出map映射}message Value {bool is_man = 1;int age = 2;}

                  网络传输效率问题

                  grpc采用HTTP2.0,相对于HTTP1.0在更快的传输和更低的成本上做了改进。有一下几个基本点:

                  1. HTTP2未改变HTTP的语义(如GET/POST等),只是在传输上优化
                  2. 引入帧,流的概念,在TCP连接中,可以区分多个request和response
                  3. 一个域名只会有一个TCP连接,借助帧,流可以实现多路复用,降低资源消耗
                  4. 引入二进制编码,降低header带来的空间占用
                  • HTTP1.1核心问题在于:在同一个TCP连接中,没办法区分response是属于哪个请求,一旦多个请求返回的文本内容混在一起,则没法区分数据归属于哪个请求,所以请求只能一个个串行排队发送。这直接导致了TCP资源的闲置。
                  • HTTP2为了解决这个问题,提出了 流 的概念,每一次请求对应一个流,有一个唯一ID,用来区分不同的请求。基于流的概念,进一步提出了 帧 ,一个请求的数据会被分成多个帧,方便进行数据分割传输,每个帧都唯一属于某一个流ID,将帧按照流ID进行分组,即可分离出不同的请求。这样同一个TCP连接中就可以同时并发多个请求,不同请求的帧数据可穿插在一起,根据流ID分组即可。HTTP2.0基于这种二进制协议的乱序模式 (Duplexing),直接解决了HTTP1.1的核心痛点,通过这种复用TCP连接的方式,不用再同时建多个连接,提升了TCP的利用效率。

                    gRPC的4种模式

                    一元RPC模式

                    一元RPC模式也被称为简单RPC模式,当客户端调用服务端的远程方法时,客户端发送请求到服务端并且获取一个响应,与响应一起发送的还有状态细节以及trailer元数据。

                    服务端流RPC模式

                    在服务器端流RPC模式中,服务器端在接受到客户端额请求消息后,会发回一个响应的序列。这种多个响应所组成的序列被称为流。在将所有的服务器端响应发送完毕之后,服务器端会以trailer元数据的形式将其状态发送给客户端,从而标记流结束。

                    客户端流RPC

                    在客户端流 RPC 模式中,客户端会发送多个请求给服务器端,而不再是单个请求。服务器端则会发送一个响应给客户端。但是,服务器端不一定要等到从客户端接收到所有消息后才发送响应。基于这样的逻辑,我们可以在接收到流中的一条消息或几条消息之后就发送响应,也可以在读取完流中的所有消息之后再发送响应。

                    双向流RPC模式

                    在双向流RPC模式中,客户端以消息流的形式发请求给服务端,服务端也以消息流的形式响应。调用必须有客户端发起,但在此之后,通信完全基于gRPC客户端和服务端的应用程序逻辑。

                    gRPC同步异步

                    gRPC调用关系图

                    上图列出了gRPC基础概念及其关系图。其中包括:Service(定义)、RPC、API、Client、Stub、Channel、Server、Service(实现)、ServiceBuilder等。

                    接下来,以官方提供的example/helloworld为例说明。

                    proto文件

                    syntax = "proto3";option java_multiple_files = true;option java_package = "io.grpc.examples.helloworld";option java_outer_classname = "HelloWorldProto";option objc_class_prefix = "HLW";package helloworld;// The greeting service definition.service Greeter {  // Sends a greeting  rpc SayHello (HelloRequest) returns (HelloReply) {}}// The request message containing the user's name.message HelloRequest {  string name = 1;}// The response message containing the greetingsmessage HelloReply {  string message = 1;}

                    Client

                    class Greeterclient是Client,是对Stub封装;通过Stub可以真正调用RPC请求。

                    class GreeterClient { public:  GreeterClient(std::shared_ptr channel)      : stub_(Greeter::NewStub(channel)) {}  // Assembles the client's payload, sends it and presents the response back  // from the server.  std::string SayHello(const std::string& user) {    // Data we are sending to the server.    HelloRequest request;    request.set_name(user);    // Container for the data we expect from the server.    HelloReply reply;    // Context for the client. It could be used to convey extra information to    // the server and/or tweak certain RPC behaviors.    ClientContext context;    // The actual RPC.    Status status = stub_->SayHello(&context, request, &reply);    // Act upon its status.    if (status.ok()) {      return reply.message();    } else {      std::cout 

上一篇:Flutter-底部弹出框(Widget层级)

下一篇:netty服务器怎么设置远程?