百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

HTTP2 协议上的 gRPC(你知道计算机上有哪些网络协议?)

ccwgpt 2024-10-13 01:31 46 浏览 0 评论

HTTP2 协议上的 gRPC

本文档作为 gRPC 在 HTTP2 草案17框架上的实现的详细描述,假设你已经熟悉 HTTP2 的规范。产品规则采用的是ABNF 语法

大纲

以下是 gRPC 请求和应答消息流中一般的消息顺序:

  • 请求 → 请求报头 *有定界符的消息 EOS
  • 应答 → 应答报头 *有定界符的消息 EOS
  • 应答 → (应答报头 *有定界符的消息 跟踪信息) / 仅仅跟踪时

请求

  • 请求 → 请求报头 *界定的消息 EOS 请求报头是通过报头+联系帧方式以 HTTP2 报头来发送的。
  • 请求报头 → 调用定义 *自定义元数据
  • 调用定义 → 方法模式路径TE [授权] [超时] [内容类型] [消息类型] [消息编码] [接受消息类型] [用户代理]
  • 方法 → “:method POST”
  • 模式 → “:scheme ” (“http” / “https”)
  • 路径 → “:path” {开放的 API 对应的方法路径}
  • Authority → “:authority” {授权的对应的虚拟主机域名}
  • TE → “te” “trailers” # 用来检测不兼容的代理
  • 超时 → “grpc-timeout” 超时时间值 超时时间单位
  • 超时时间值 → {至少8位数字正整数的 ASCII 码字符串}
  • 超时时间单位 → 时 / 分 / 秒 / 毫秒 / 微秒 / 纳秒
  • → “H”
  • → “M”
  • → “S”
  • 毫秒 → “m”
  • 微秒 → “u”
  • 纳秒 → “n”
  • 内容类型 → “content-type” “application/grpc” [(“+proto” / “+json” / {自定义})]
  • 内容编码 → “gzip” / “deflate” / “snappy” / {自定义}
  • 消息编码 → “grpc-encoding” Content-Coding
  • 接受消息编码 → “grpc-accept-encoding” Content-Coding *("," Content-Coding)
  • 用户代理 → “user-agent” {结构化的用户代理字符串}
  • 消息类型 → “grpc-message-type” {消息模式的类型名}
  • 自定义数据 → 二进制报头 / ASCII 码报头
  • 二进制报头 → {以“-bin”结尾小写的报头名称的 ASCII 码 } {以 base64 进行编码的值}
  • ASCII 码报头 → {小写报头名称的 ASCII 码} {}

HTTP2 需要一个在其他报头之前以“:”开始的保留报头。额外的实现应该在保留报头后面马上传送超时信息,并且应该在发送自定义元数据前发送调用定义报头。 如果超时信息被遗漏,服务端会认为是无限时长的超时。客户端实现可以根据发布需要自由地发送一个默认最小超时时间。 自定义元数据是应用层定义的任意的键值对集合。除了 HTTP2 报头部总长度的传输限制外,唯一的约束就是以“grpc-”开始的报头名称是为将来使用保留的。

注意 HTTP2 并不允许随意使用字节序列来作为报头值,所以二进制的报头值必须使用 Base64 来编码,参见https://tools.ietf.org/html/rfc4648#section-4。 实现必须接受填充的和非填充的值,并且发出非填充的值。应用以“-bin”结尾的名称来定义二进制报头。运行时库在报头被发送和接收时,用这个后缀来检测二进制报头并且正确地在报头被发送和接收时进行 Base64 编码和解码。

界定的消息的重复序列通过数据帧来进行传输。

  • 界定的消息 → 压缩标志 消息长度 消息
  • 压缩标志 → 0 / 1 # 编码为 1 byte 的无符号整数
  • 消息长度 → {消息长度} # 编码为 4 byte 的无符号整数
  • 消息 → *{二进制字节}

压缩标志 值为1 表示消息的二进制序列通过消息编码报头声明的机制进行压缩,为0表示消息的字节码没有进行编码。压缩上下文不在消息编辑间维护,声明必须为流中的每个消息创建一个新的上下文。假如 压缩标志 被遗漏了,那么压缩标志 必须为0。

对请求来讲,EOS (end-of-stream)以最后接收到的数据帧出现 END_STREAM 标志为准。 在请求流需要关闭但是没有数据继续发送的情况下,代码必须发送包含这个标志的空数据帧。

应答

  • 应答 → (应答报头 界定的消息 跟踪信息) / 仅仅跟踪
  • 应答报头 → HTTP 状态 [消息编码] [消息接受编码] 内容类型 *自定义元数据
  • 仅仅跟踪 → HTTP 状态 内容类型 跟踪消息
  • 跟踪消息 → 状态 [状态消息] *自定义元数据
  • HTTP状态 → “:status 200”
  • 状态 → “grpc-status” <状态码的 ASCII 字符串>
  • 状态消息 → “grpc-message” <状态描述文本对应的 ASCII 字符串>

应答报头仅仅跟踪 分别在一个HTTP2报头帧块里发送。大多数应答期望既有报头又有跟踪消息,但是调用允许仅仅跟踪生成一个立即的错误。假如状态码是 OK 的话,则必须在跟踪消息里发送状态。 对于应答来讲,通过在最后一个接收的包含跟踪信息的报头帧里提供一个 END_STREAM 标志来表明流结束。

实现应当会让中断的部署在应答里发送一个非200的HTTP状态码和一系列非GRPC内容类型并且省略状态状态消息。 当发生这种情况时实现应当合成状态状态消息来扩散到应用层。

例子

单项调用HTTP2帧序列例子

请求


HEADERS (flags = END_HEADERS)

:method = POST

:scheme = http

:path = /google.pubsub.v2.PublisherService/CreateTopic

:authority = pubsub.googleapis.com

grpc-timeout = 1S

content-type = application/grpc+proto

grpc-encoding = gzip

authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v




DATA (flags = END_STREAM)

<Delimited Message>

应答


HEADERS (flags = END_HEADERS)

:status = 200

grpc-encoding = gzip




DATA

<Delimited Message>




HEADERS (flags = END_STREAM, END_HEADERS)

grpc-status = 0 # OK

trace-proto-bin = jher831yy13JHy3hc

用户代理

当协议不需要一个用户代理时,建议客户端提供一个结构化的用户代理字符串来对要调用的库、版本和平台提供一个基本的描述来帮助在异质的环境里进行问题诊断。库开发者建议使用以下结构:


User-Agent → “grpc-” Language ?(“-” Variant) “/” Version ?( “ (“  *(AdditionalProperty “;”) “)” )

例如


grpc-java/1.2.3

grpc-ruby/1.2.3

grpc-ruby-jruby/1.3.4

grpc-java-android/0.9.1 (gingerbread/1.2.4; nexus5; tmobile)

HTTP2 传输映射

流识别

所有的 GRPC 调用需要定义指定一个内部 ID。我们将在这个模式里使用 HTTP2 流 ID 来作为调用标识。注意:这些 ID 在一个打开的 HTTP2 会话里是前后关联的,在一个处理多个 HTTP2 会话的进程里不是唯一的,也不能被用作 GUID。

数据帧

数据帧边界与界定消息的边界无关,实现时不应假定它们有一致性。

错误

当应用错误或运行时错误在 PRC 调用过程中出现时,状态状态消息应当通过跟踪消息发送。

在有些情况下可能消息流的帧已经中断,RPC 运行时会选择使用 RST_STREAM 帧来给对方表示这种状态。RPC 运行时声明应当将 RST_STREAM 解释为流的完全关闭,并且将错误传播到应用层。 以下为从 RST_STREAM 错误码到 GRPC 的错误码的映射:

HTTP2 编码

GRPC 编码

NO_ERROR(0)

INTERNAL -一个显式的GRPC OK状态应当被发出,但是这个也许在某些场景里会被侵略性地使用

PROTOCOL_ERROR(1)

INTERNAL

INTERNAL_ERROR(2)

INTERNAL

FLOW_CONTROL_ERROR(3)

INTERNAL

SETTINGS_TIMEOUT(4)

INTERNAL

STREAM_CLOSED

无映射,因为没有打开的流来传播。实现应记录。

FRAME_SIZE_ERROR

INTERNAL

REFUSED_STREAM

UNAVAILABLE-表示请求未作处理且可以重试,可能在他处重试。

CANCEL(8)

当是由客户端发出时映射为调用取消,当是由服务端发出时映射为 CANCELLED。注意服务端在需要取消调用时应仅仅使用这个机制,但是有效荷载字节顺序是不完整的

COMPRESSION_ERROR

INTERNAL

CONNECT_ERROR

INTERNAL

ENHANCE_YOUR_CALM

RESOURCE_EXHAUSTED...并且运行时提供有额外的错误详情,表示耗尽资源是带宽

INADEQUATE_SECURITY

PERMISSION_DENIED... 并且有额外的信息表明许可被拒绝,因为对调用来说协议不够安全

安全

HTTP2 规范当使用 TLS 时强制使用 TLS 1.2 及以上的版本,并且在部署上对允许的密码施加一些额外的限制以避免已知的比如需要 SNI 支持的问题。并且期待 HTTP2 与专有的传输安全机制相结合,这些传输机制的规格说明不能提供有意义的建议。

连接管理

GOAWAY 帧

服务端发出这种帧给客户端表示服务端在相关的连接上不再接受任何新流。这种帧包含服务端最后成功接受的流的ID。客户端应该认为任何在最后成功的流后面初始化的任意流为 UNAVAILABLE,并且在别处重试这些调用。客户端可以自由地在已经接受的流上继续工作直到它们完成或者连接中断。 服务端应该在终止连接前发送 GOAWAY 帧,以可靠地通知客户端哪些工作已经被服务端接受并执行。

PING 帧

客户端和服务端均可以发送一个 PING 帧,对方必须精确回显它们所接收到的信息。这可以被用来确认连接仍然是活动的,并且能够提供估计端对端延迟估计的方法。假如服务端初始的 PING 在最后期限仍然没有收到运行时所期待的应答的话,所有未完成的调用将会被以取消状态关闭。一个客户端期满的初始的PING则会导致所有的调用被以用不可用状态关闭。注意PING的频率高度依赖于网络环境,实现可以根据网络和应用需要,自由地调整PING频率。

连接失败

假如客户端检测到连接失败,所有的调用都会被以不可用状态关闭。而服务端侧则所有已经打开的调用都会被以取消状态关闭。

附录 A - Protobuf 上的 GRPC

用 protobuf 定义的服务接口可以通过 protoc 的代码生成扩展简单地映射成 GRPC ,以下定义了所用的映射:

  • 路径 → / 服务名 / {方法名}
  • 服务名 → ?( {proto 包名} "." ) {服务名}
  • 消息类型 → {全路径 proto 消息名}
  • 内容类型 → "application/grpc+proto"

相关推荐

十分钟让你学会LNMP架构负载均衡(impala负载均衡)

业务架构、应用架构、数据架构和技术架构一、几个基本概念1、pv值pv值(pageviews):页面的浏览量概念:一个网站的所有页面,在一天内,被浏览的总次数。(大型网站通常是上千万的级别)2、u...

AGV仓储机器人调度系统架构(agv物流机器人)

系统架构层次划分采用分层模块化设计,分为以下五层:1.1用户接口层功能:提供人机交互界面(Web/桌面端),支持任务下发、实时监控、数据可视化和报警管理。模块:任务管理面板:接收订单(如拣货、...

远程热部署在美团的落地实践(远程热点是什么意思)

Sonic是美团内部研发设计的一款用于热部署的IDEA插件,本文其实现原理及落地的一些技术细节。在阅读本文之前,建议大家先熟悉一下Spring源码、SpringMVC源码、SpringBoot...

springboot搭建xxl-job(分布式任务调度系统)

一、部署xxl-job服务端下载xxl-job源码:https://gitee.com/xuxueli0323/xxl-job二、导入项目、创建xxl_job数据库、修改配置文件为自己的数据库三、启动...

大模型:使用vLLM和Ray分布式部署推理应用

一、vLLM:面向大模型的高效推理框架1.核心特点专为推理优化:专注于大模型(如GPT-3、LLaMA)的高吞吐量、低延迟推理。关键技术:PagedAttention:类似操作系统内存分页管理,将K...

国产开源之光【分布式工作流调度系统】:DolphinScheduler

DolphinScheduler是一个开源的分布式工作流调度系统,旨在帮助用户以可靠、高效和可扩展的方式管理和调度大规模的数据处理工作流。它支持以图形化方式定义和管理工作流,提供了丰富的调度功能和监控...

简单可靠高效的分布式任务队列系统

#记录我的2024#大家好,又见面了,我是GitHub精选君!背景介绍在系统访问量逐渐增大,高并发、分布式系统成为了企业技术架构升级的必由之路。在这样的背景下,异步任务队列扮演着至关重要的角色,...

虚拟服务器之间如何分布式运行?(虚拟服务器部署)

  在云计算和虚拟化技术快速发展的今天,传统“单机单任务”的服务器架构早已难以满足现代业务对高并发、高可用、弹性伸缩和容错容灾的严苛要求。分布式系统应运而生,并成为支撑各类互联网平台、企业信息系统和A...

一文掌握 XXL-Job 的 6 大核心组件

XXL-Job是一个分布式任务调度平台,其核心组件主要包括以下部分,各组件相互协作实现高效的任务调度与管理:1.调度注册中心(RegistryCenter)作用:负责管理调度器(Schedule...

京东大佬问我,SpringBoot中如何做延迟队列?单机与分布式如何做?

京东大佬问我,SpringBoot中如何做延迟队列?单机如何做?分布式如何做呢?并给出案例与代码分析。嗯,用户问的是在SpringBoot中如何实现延迟队列,单机和分布式环境下分别怎么做。这个问题其实...

企业级项目组件选型(一)分布式任务调度平台

官网地址:https://www.xuxueli.com/xxl-job/能力介绍架构图安全性为提升系统安全性,调度中心和执行器进行安全性校验,双方AccessToken匹配才允许通讯;调度中心和执...

python多进程的分布式任务调度应用场景及示例

多进程的分布式任务调度可以应用于以下场景:分布式爬虫:importmultiprocessingimportrequestsdefcrawl(url):response=re...

SpringBoot整合ElasticJob实现分布式任务调度

介绍ElasticJob是面向互联网生态和海量任务的分布式调度解决方案,由两个相互独立的子项目ElasticJob-Lite和ElasticJob-Cloud组成。它通过弹性调度、资源管控、...

分布式可视化 DAG 任务调度系统 Taier 的整体流程分析

Taier作为袋鼠云的开源项目之一,是一个分布式可视化的DAG任务调度系统。旨在降低ETL开发成本,提高大数据平台稳定性,让大数据开发人员可以在Taier直接进行业务逻辑的开发,而不用关...

SpringBoot任务调度:@Scheduled与TaskExecutor全面解析

一、任务调度基础概念1.1什么是任务调度任务调度是指按照预定的时间计划或特定条件自动执行任务的过程。在现代应用开发中,任务调度扮演着至关重要的角色,它使得开发者能够自动化处理周期性任务、定时任务和异...

取消回复欢迎 发表评论: