gRPC知识归档

news2024/12/26 11:45:48

文章目录

  • 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 greeting
  rpc 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.coloradmin.cn/o/1482000.html

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

相关文章

ChatGPT与GEE+ENVI+python高光谱,多光谱等成像遥感数据处理技术

原文链接&#xff1a;ChatGPT与GEEENVIpython高光谱&#xff0c;多光谱等成像遥感技术 第一遥感科学与AI基础 一&#xff1a;遥感科学的基本原理和历史 从摄影侦察到卫星图像 遥感的基本原理 遥感的典型应用 最新进展和未来趋势 二&#xff1a;ChatGPT 什么是ChatGPT&a…

数字口岸再升级:广西二期项目助力口岸通关提速运营增效!

在数字口岸相关政策的引领下&#xff0c;广西与RCEP其他成员国进出口规模有力攀升&#xff0c;大力推动了广西向海经济&#xff0c;临港产业集群不断壮大&#xff0c;大宗商品贸易快速增长。据海关统计&#xff0c;2023年&#xff0c;广西进出口总值6936.5亿元人民币&#xff0…

k8s中容器的调度与创建:CRI,cgroup

container调度与创建 选自&#xff1a;K8s、CRI与container - packy的文章 - 知乎 https://zhuanlan.zhihu.com/p/102897620 Cgroup创建&#xff1a; cgexec -g cpu,memory:$UUID \ > unshare -uinpUrf --mount-proc \ > sh -c "/bin/hostname $UUID &…

关于vue中关于eslint报错的问题

1 代码保存的时候会自动将单引号报错为双引号 导致eslint报错的问题&#xff0c; 解决思路&#xff1a; 在项目根目录下新建一个.prettierrc.json文件 { “tabWidth”: 2,“useTabs”: false,“singleQuote”: true,“semi”: false} 2 关于报错代码的时候 出现尾随逗号报错…

MySQL 多表查询 连接查询 外连接

介绍 MySQL 多表查询 连接查询 内连接 外连接分为两种&#xff0c;左外和右外连接&#xff0c; 左外&#xff1a;相当于查询表1(左表)的所有数据 包含 表1和表2交集部分的数据,完全包含左表的数据 右外&#xff1a;相当于查询表2(右表)的所有数据 包含 表1和表2交集部分的数据…

《PySide6/PyQt6快速开发与实战》P111被省略了的案例

编程环境&#xff1a;Fedora, QtCreator 见代码&#xff1a; # This Python file uses the following encoding: utf-8 import sys from PySide6.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget from PySide6.QtGui import QPalette #, QColo…

Scratch 第十三课-飞机大战游戏

第十三课-飞机大战游戏 学习目标 这节课我们做一款大家都爱玩的飞机大战游戏&#xff0c;学习重点&#xff1a; 如何导入外部角色如何让飞机发射子弹鼠标控制角色移动 程序设计 程序分析 &#xff1a; 飞机大战游戏相信很多小朋友都玩过&#xff0c;我方飞机在下方&#xf…

双通道音频功率放大电路,外接元件少, 通道分离性好,3V 的低压下可正常使用——D2025

D2025 为立体声音频功率放大集成电路&#xff0c;适用于各类袖珍或便携式立体声 收录机中作功率放放大器。 D2025 采用 DIP16 封装形式。 主要特点&#xff1a;  适用于立体声或 BTL 工作模式  外接元件少  通道分离性好  电源电压范围宽&#xff08;3V~12V &#xff…

Unity3d Shader篇(十)— 渐变纹理

文章目录 前言一、什么是Unlity渐变纹理Shader&#xff1f;1. 渐变纹理Shader工作原理2. 渐变纹理&#xff1f;3. 渐变纹理的优缺点优点&#xff1a;缺点&#xff1a; 4. 渐变纹理例图 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函…

【Flutter 面试题】解释 Flutter的热重载(Hot Reload)功能

【Flutter 面试题】解释 Flutter的热重载&#xff08;Hot Reload&#xff09;功能 文章目录 写在前面解答补充说明 写在前面 关于我 &#xff0c;小雨青年 &#x1f449; CSDN博客专家&#xff0c;GitChat专栏作者&#xff0c;阿里云社区专家博主&#xff0c;51CTO专家博主。2…

JVM运行时数据区——本地方法接口和本地方法栈

1、本地方法接口 虽然Java语言使用非常广泛&#xff0c;但是有些事务Java仍然无法处理。例如线程相关的功能&#xff0c;在线程类当中就有很多本地方法接口。那么Java如何来处理这些问题呢&#xff1f;Java设计师提出了一种解决方案就是本地方法接口。本贴将会讲解本地方法接口…

spark sql 转换字符串数组成多列结构

背景 在平时使用spark sql分析数据时&#xff0c;特别是分析从mysql的表入仓的hive表时&#xff0c;我们会经常和字符串数组的列打交道&#xff0c;而且这种情况下我们一般都需要把一行字符串数组的行数据转成多列的形式&#xff0c;我们看下怎么写这个sql spark sql 转换字符…

idea中maven配置(一次成功,全部细节都有)

写这篇文章的原因是maven的配置很简单&#xff0c;但是也很容易出错&#xff0c;我连配了两台电脑的maven出现了各种小错误&#xff0c;参考了以下两篇博文IDEA配置Maven教程&#xff08;超详细版~)_idea maven配置教程-CSDN博客 一次包会——最新IDEA配置Maven指南&#xff0…

(学习日记)2024.03.01:UCOSIII第三节

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

ABAP - OOALV 单元格 F4实现

方式一:使用标准数据表&#xff0c;FIELDCAT字段设置值 gs_fieldcat-ref_table X. "列可编辑gs_fieldcat-ref_table MARA. "F4 参考表gs_fieldcat-ref_field MATNR. "F4 参考字段 方式二.使用自定义数据 &#xff0c;实现效果如下图…

git根据文件改动将文件自动添加到缓冲区

你需要修改以下脚本中的 use_cca: false 部分 #!/bin/bash# 获取所有已修改但未暂存的文件 files$(git diff --name-only)for file in $files; do# 检查文件中是否存在"use_cca: false"if grep -q "use_cca: false" "$file"; thenecho "Ad…

【ue5】滑铲系统蓝图笔记

大致逻辑如下&#xff1a; 一、导入动画 滑铲蹲待机蹲行走 导入到文件夹中 可以右键设置颜色&#xff0c;便于区分。 二、调整动画 1.启动根运动 启动根运动后&#xff0c;人物才可以位移&#xff0c;不然只能在原地。 打开动画序列&#xff0c;勾选启用根运动Enabled…

【排序算法】基数排序

一&#xff1a;基本概念 1.1 基数排序(桶排序)介绍 基数排序&#xff08;radix sort&#xff09;属于“分配式排序”&#xff08;distribution sort&#xff09;&#xff0c;又称“桶子法”&#xff08;bucket sort&#xff09;或bin sort&#xff0c;顾名思义&#xff0c;它是…

Python读取hbase数据库

1. hbase连接 首先用hbase shell 命令来进入到hbase数据库&#xff0c;然后用list命令来查看hbase下所有表&#xff0c;以其中表“DB_level0”为例&#xff0c;可以看到库名“baotouyiqi”是拼接的&#xff0c;python代码访问时先连接&#xff1a; def hbase_connection(hbase…

如何开好一家汽车美容店,汽车美容保养与装饰教学

一、教程描述 本套教程共由17张VCD组合而成&#xff0c;教程内容主要包括&#xff1a;美容店的设立和管理&#xff0c;汽车系统与内部结构&#xff0c;汽车美容工具与美容设备&#xff0c;美容用品的选择与使用&#xff0c;车身打蜡镀膜与内外清洁&#xff0c;车身抛光与漆面处…