gRPC知识归档

文章目录

  • 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++ class
message Request {
//类型 | 字段名字| 标号int64 user_id = 1;string name = 2;
}
message Response {repeated int64 ids = 1; // repeated 表示数组Value info = 2; // 可嵌套对象map<int, Value> 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 greetingrpc SayHello (HelloRequest) returns (HelloReply) {}
}// The request message containing the user's name.
message HelloRequest {string name = 1;
}// The response message containing the greetings
message HelloReply {string message = 1;
}

Client

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

class GreeterClient {public:GreeterClient(std::shared_ptr<Channel> 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 << status.error_code() << ": " << status.error_message()<< std::endl;return "RPC failed";}}private:std::unique_ptr<Greeter::Stub> stub_;
};

Channel提供一个特定gRPC server的主机和端口简历的连接。
Stub就是在Channel的基础上创建而成。

target_str = "localhost:50051";
auto channel = grpc::CreateChannel(target_str, grpc::InsecureChannelCredentials());
GreeterClient greeter(channel);
std::string user("world");
std::string reply = greeter.SayHello(user);

server

Server端需要实现对应的RPC,所有的RPC组成了Sevice

// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {Status SayHello(ServerContext* context, const HelloRequest* request,HelloReply* reply) override {std::string prefix("Hello ");reply->set_message(prefix + request->name());return Status::OK;}
};

Server的创建需要一个Builder,添加上监听的地址和端口,注册上该端口上绑定的服务,最后构建出Server并且启动。

ServerBuilder builder;// Listen on the given address without any authentication mechanism.builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());// Register "service" as the instance through which we'll communicate with// clients. In this case it corresponds to an *synchronous* service.builder.RegisterService(&service);// Finally assemble the server.std::unique_ptr<Server> server(builder.BuildAndStart());

RPC和API的区别:RPC(Remote Procedure Call)是一次远程过程调用的整个动作,而API(Application Programming Interface)是不同语言实现RPC中的具体接口。一个RPC可能对应多种API,比如同步的,异步的,回调的。

异步相关概念

不管Client还是Server,异步gRPC都是利用CompletionQueue API进行异步操作。基本流程:
- 绑定一个CompletionQueue到一个RPC调用
- 利用唯一的void* Tag进行读写
- 调用CompletionQueue::Next()等待操作完成,完成后通过唯一的Tag来判断对应什么请求/返回进行后续操作

异步Client

greeter_async_client.cc中是异步Client的Demo,其中只有一次请求,逻辑简单

  • 创建CompletionQueue
  • 创建RPC(即clientAsyncResponseReader<HelloReply>),这里有两种方式:
    • stub_->PrepareAsyncSayHello() + rpc->StartCall()
    • stub_->AsyncSayHello()
  • 调用rpc->Finish()设置请求消息reply和唯一的tag关联,将请求发送出去。
  • 使用cq.Next()等待Completion Queue返回响应消息体,通过tag关联对应请求。
异步Server

RequestSayHello()这个函数没有任何说明。只是说:“we request that the system start processing SayHello requset.”也没有说和cq_->Next(&tag, &ok);的关系。我来说一下流程:
- 创建一个CallData,初始构造列表中将状态设置为CREATE
- 构造函数中,调用Process()成员函数,调用service_->RequestSayHello()后,状态变更为PROCESS:
- 传入ServerContext ctx_
- 传入HelloRequest request_
- 传入ServerAsyncResponsewriter<HelloReply> responder_
- 传入ServerCompletionQueue* cq_
- 将对象自身的地址作为tag传入
- 该动作,能将事件加入事件循环,可以在CompletionQueue中等待
- 收到请求,cp->Next()的阻塞结束并且返回,得到tag,即上次传入的CallData对象
- 调用tag对应CallData对象Process(),此时状态Process
- 创建新的CallData对象以接受新请求
- 处理消息并且设置reply_
- 将状态设置为FINISH
- 调用responder_.Finish()将返回发送给客户端
- 该动作,能将事件加入到循环,可以将CompletionQueue中等待
- 发送完毕,cp->Next()的阻塞结束并且返回,得到tag。现实中,如果发送有异常应当有其他处理。
- 调用tag对应的CallData对象proceed,此时状态为FINISHdelete this清理自己,一条消息处理完成。

关系图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/713152.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【airtest】自动化入门教程(二)airtest操作

目录 一、touch 二、wait 三、swipe 四、exists 五、text 六、keyevent 七、snapshot 八、sleep 九、断言 9.1 assert_exists 9.2 assert_not_exists 9.3 assert_equal 9.4 assert_not_equal 前言&#xff1a;本文主要针对aritest部分的基础操作,aritest是一个跨平…

网络编程第二天

1.基于TCP的通信(面向连接的通信) 服务器代码实现&#xff1a; #include <myhead.h> #define IP "192.168.126.91" #define PORT 9999 int main(int argc, const char *argv[]) {//1、创建套接字int sfd-1;if((sfdsocket(AF_INET,SOCK_STREAM,0))-1){perror(…

ES系列之Logstash实战入门

概述 作为ELK技术栈一员&#xff0c;Logstash用于将数据采集到ES&#xff0c;通过简单配置就能把各种外部数据采集到索引中进行保存&#xff0c;可提高数据采集的效率。 原理 数据源提供的数据进入Logstash的管道后需要经过3个阶段&#xff1a; input&#xff1a;负责抽取数…

【ArcPy】批量读取文件夹excel中XY并转为点shp

示例展示 代码 只读取excel中含有XY字段的文件&#xff0c;并将矢量命名为excel文件名称。 import os import pandas as pd import arcpy folder_path r"C:\Users\admin\Desktop\excelfile" extension"xlsx" files [file for file in os.listdir(folder…

SpringCloud gateway限流无效,redis版本低的问题

在使用springCloud gateway的限流功能的时候&#xff0c;配置RedisRateLimiter限流无效&#xff0c;后来发现是Redis版本过低导致的问题&#xff0c;实测 Redis版本为3.0.504时限流无效&#xff0c;改用7.0.x版本的Redis后限流生效。查了资料发现很多人都遇见过这个问题&#x…

RedisTemplate 序列化成功,反序列化失败List, Set, Map失败

RedisTemplate 序列化成功&#xff0c;反序列化失败List, Set, Map失败 异常信息RedisTemplate配置异常原因错误代码示例解决方法 序列化成功&#xff0c;反序列化失败 异常信息 Caused by: com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve ty…

小程序事件处理

事件处理 一个应用仅仅只有界面展示是不够的&#xff0c;还需要和用户做交互&#xff0c;例如&#xff1a;响应用户的点击、获取用户输入的值等等&#xff0c;在小程序里边&#xff0c;我们就通过编写 JS 脚本文件来处理用户的操作 1. 事件绑定和事件对象 小程序中绑定事件与…

React之组件定义和事件处理

一、组件的分类 在react中&#xff0c;组件分为函数组件和class组件&#xff0c;也就是无状态组件和有状态组件。 * 更过时候我们应该区别使用无状态组件&#xff0c;因为如果有状态组件会触发生命周期所对应的一些函数 * 一旦触发他生命周期的函数&#xff0c;它就会影响当前项…

如何设置从小程序跳转到其它小程序

​有的商家有多个小程序&#xff0c;希望能够通过一个小程序链接到所有其它小程序&#xff0c;用户可以通过点击跳转链接实现从一个小程序跳转到另一个小程序。要怎么才能实现这样的跳转呢。下面具体介绍。 1. 设置跳转。在小程序管理员后台->分类管理&#xff0c;添加一个…

ssm个人学习01

Spring配置文件: spring环境的搭建: 1:导入对应的spring坐标 也就是依赖 2:编写controller, service, dao相关的代码 3:创建配置文件(在resource下面配置文件) 例如:applicationContext.xml <bean id "" class ""> <property name "&…

工作电压范围宽的国产音频限幅器D2761用于蓝牙音箱,输出噪声最大仅-90dBV

近年来随着相关技术的不断提升&#xff0c;音箱也逐渐从传统的音箱向智能音箱、无线音箱升级。同时在消费升级的背景下&#xff0c;智能音箱成为人们提升生活品质的方式之一。智能音箱是智能化和语音交互技术的产物&#xff0c;具有点歌、购物、控制智能家居设备等功能&#xf…

python水表识别图像识别深度学习 CNN

python水表识别&#xff0c;图像识别深度学习 CNN&#xff0c;Opencv,Keras 重点&#xff1a;项目和文档是本人近期原创所作&#xff01;程序可以将水表图片里面的数据进行深度学习&#xff0c;提取相关信息训练&#xff0c;lw1.3万字重复15%&#xff0c;可以直接上交那种&…

Vue中<style scoped lang=“scss“>的含义

这段代码中的<style scoped lang"scss">是HTML和Vue框架结合使用时常见的一个模式&#xff0c;具体含义如下&#xff1a; scoped&#xff1a;这是一个Vue.js特有的属性&#xff0c;用来指定样式只应用于当前组件的元素。没有这个属性时&#xff0c;样式会全局应…

elasticsearch7.17 terms聚合性能提升90%+

背景 ES7 相比于 ES6 有多个层面的优化&#xff0c;对于开源的ES而言&#xff0c;升级是必经之路。 ES的使用场景非常多&#xff0c;在升级过程中可能会遇到非预期的结果&#xff1b; 比如之前文章提到的典型案例&#xff1a;ES7.17版本terms查询性能问题 ES7.17版本terms查…

【Python笔记-FastAPI】后台任务+WebSocket监控进度

目录 一、代码示例 二、执行说明 (一) 调用任务执行接口 (二) 监控任务进度 实现功能&#xff1a; 注册后台任务&#xff08;如&#xff1a;邮件发送、文件处理等异步场景&#xff0c;不影响接口返回&#xff09;监控后台任务执行进度&#xff08;进度条功能&#xff09;支…

pclpy 点云法线

pclpy 点云法线 一、算法原理1.理论入门2.选择正确的比例 二、代码三、结果四、相关数据 一、算法原理 表面法线是几何表面的重要属性&#xff0c;在许多领域&#xff08;例如计算机图形应用程序&#xff09;中大量使用&#xff0c;以应用正确的光源来生成阴影和其他视觉效果。…

Android 混淆是啥玩意儿?

什么是混淆 Android混淆&#xff0c;是伴随着Android系统的流行而产生的一种Android APP保护技术&#xff0c;用于保护APP不被破解和逆向分析。简单的说&#xff0c;就是将原本正常的项目文件&#xff0c;对其类、方法、字段&#xff0c;重新命名a,b,c…之类的字母&#xff0c…

森林灭火利器|便携式森林消防灭火泵|恒峰智慧科技

随着人们对环境保护意识的不断提高&#xff0c;森林防火工作显得尤为重要。然而&#xff0c;传统的森林灭火方式存在诸多不便&#xff0c;如火势蔓延迅速、灭火效率低下等。为了更好地保护森林资源&#xff0c;科学家们研发出了一种便携式森林消防灭火泵&#xff0c;它的出现为…

利用css实现常见图形

1、正圆形 给正方形盒子设置圆角属性为宽高的50%。 div {width: 100px;height: 100px;background-color: plum;border-radius: 50%; } 2、胶囊形 给长方形盒子设置圆角属性为盒子高度的50%。 div {width: 200px;height: 100px;background-color: plum;border-radius: 50px…

基于C#开发OPC DA客户端——基于OPCDAAuto

OPC DA OPC DA(OPC Data Access)&#xff0c;即OPC数据访问接口&#xff0c;定义了数据交换的规范&#xff0c;包括&#xff1a;过程值、更新时间、数据品质等信息。 自动化接口中共定义了6类对象&#xff1a;OPCServer对象、OPCBrowser对象、OPCGroups对象、OPCGroup对象、O…