站在巨人的肩膀上:gRPC通过HTTP/2构建云原生时代的通信标准

gRPC:云原生时代的通信标准

gRPC将HTTP/2作为其传输层,并在此基础上定义了自身的通信语义。gRPC支持四种服务方法类型,它们都映射到HTTP/2的流模型上。

1)Unary RPC: 客户端发送单个请求,服务器返回单个响应(类似传统请求-响应)。

2)Server Streaming RPC: 客户端发送单个请求,服务器返回一个消息序列(流)。

3)Client Streaming RPC: 客户端发送一个消息序列(流),服务器返回单个响应。

4)Bidirectional Streaming RPC: 客户端和服务器都可以独立地发送一个消息序列(流)。

请求 (Request) 结构

gRPC的Request 包含请求头(Request Headers),请求体(Request Body)和EOS(end-of-stream)。

请求头使用 HTTP/2的headers, 使用HEADERS和CONTINUATION帧派发。请求头有Call-Definition和Custom-Metadata。其中grpc-前缀为 gRPC自己保留。

bash 复制代码
HEADERS (flags = END_HEADERS)
// HTTP 方法。对于 gRPC,:method标头始终为POST。
:method = POST 
// HTTP 协议。如果启用了 TLS,则协议设置为https,否则为http。
:scheme = http 
// 终端路径。对于 gRPC,此值构造为"/${包名}.${服务名}/${接口名}"。
:path = /ProductInfo/getProduct 
// 目标 URI 的虚拟主机名。
:authority = abc.com 
// 不兼容代理的检测。对于 gRPC,该值必须是"trailers"。
te = trailers 
// 调用超时时。如果未指定,server端应假定无限超时。
grpc-timeout = 1S 
// 内容类型。对于 gRPC,内容类型应以application/grpc。
content-type = application/grpc 
// 消息压缩方式。包括identity、gzip、deflate、snappy及自定义压缩方式。
grpc-encoding = gzip 
// 可选的请求头,用于访问有安全限制的终端服务。
authorization = Bearer xxxxxx

请求体使用DATA帧派发,请求体是长度前缀消息。它有一个 Compressed flag 用来表示message 是否压缩,为1表示采用了压缩算法(具体的压缩算法在HEADERS帧中定义)。后面跟着四字节的 message length 以及实际的 message。

EOS会在DATA帧里面带上了END_STREAM这个flag。用来表示请求消息的结束。

bash 复制代码
DATA (flags = END_STREAM)
<Length-Prefixed Message>

响应 (Response) 结构

gRPC的Response包含响应头(Response-Headers),响应体(Response Body)和 Trailers。

bash 复制代码
HEADERS (flags = END_HEADERS)
// 标识 HTTP 请求的状态。
:status = 200 
// 消息压缩类型。包括identity、gzip、deflate、snappy和自定义类型。
grpc-encoding = gzip 
// 内容类型。对于gRPC,content-type应该设置为application/grpc。
content-type = application/grpc 

发完响应头,使用DATA帧派发响应体。响应体是长度前缀消息。

bash 复制代码
DATA
<Length-Prefixed Message>

结束标志不与数据帧一起发送,而是作为单独的头部发送,称为Trailers。 如果遇到了错误,也可以直接返回 Trailers-Only。

Trailer是一种特殊的元数据,通常包含有关执行的状态信息,例如状态码( grpc-status)和状态消息(grpc-message)

gRPC之所以要用单独的Trailers来标志响应结束。是因为在streaming模式下,所有消息没有传输完成之前,gRPC也不知道要传什么样的grpc-status 。

bash 复制代码
HEADERS (flags = END_STREAM, END_HEADERS)
// gRPC 状态代码
grpc-status = 0 # OK 
// 错误描述。可选的,仅在处理请求出现错误时设置。
grpc-message = xxxxxx 

服务描述

gRPC 利用 .proto 文件中的 service 来定义 RPC 接口。

bash 复制代码
// 文件: demo/hello/greeter.proto
syntax = "proto3";

package demo.hello;

// Greeter 服务定义
service Greeter {
  // SayHello 方法定义
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// 请求消息结构
message HelloRequest {
  string name = 1;
}

// 响应消息结构
message HelloReply {
  string message = 1;
}

在上述 .proto 文件中,定义了一个名为 Greeter 的服务,它包含一个名为 SayHello 的方法。该方法接收 HelloRequest 消息并返回 HelloReply 消息。gRPC工具链会基于此IDL生成各种语言的客户端存根(stub)和服务端骨架(skeleton)。开发者通过调用存根上的方法,就如同调用本地方法一样,gRPC框架会处理底层的序列化、网络通信和方法分发。

一个 gRPC 定义包含三个部分,包名、服务名和接口名,连接规则如下:

bash 复制代码
/${包名}.${服务名}/${接口名}

SayHello的包名是demo.hello,服务名是Greeter,接口名是SayHello,所以对应的路径就是 /demo.hello.Greeter/SayHello。

bash 复制代码
HEADERS (flags = END_HEADERS) 
:method = POST
:scheme = http
:path = /demo.hello.Greeter/SayHello
:authority = grpc.demo.com
content-type = application/grpc

DATA (flags = END_STREAM) 
<Length-Prefixed Message>

gRPC基于这样的一个设计理念:定义一个服务,及其被远程调用的方法(方法名称、入参、出参)。开发者可以像调用本地方法一样,使用gRPC客户端存根(stub)调用远程机器上 gRPC 服务的方法。gRPC 的客户端和服务端都可以用任何支持 gRPC 的语言来实现,例如一个 gRPC 服务端可以是 C++语言编写的,以供 Ruby 语言的 gRPC 客户端和 JAVA 语言的 gRPC 客户端调用,如下图所示。

未完待续.

很高兴与你相遇!如果你喜欢本文内容,记得关注哦!

相关推荐
武子康5 分钟前
调查研究-156 Vercel 全栈应用 前端零配置极速上线:Serverless + 边缘网络 + CI/CD 全栈实战
前端·网络·ci/cd·ai·云原生·serverless·vecel
牧羊狼的狼7 分钟前
基于阿里云落地SpringCloudAlibaba云原生微服务:从部署、CI/CD到性能调优、线上排障全体系实战
阿里云·微服务·云原生
拾光Ծ2 小时前
【Linux网络】计算机网络入门:网络产生与协议
linux·网络·网络协议·tcp/ip·计算机网络
这个DBA有点耶9 小时前
云上运维新挑战:当数据库不再“看得见摸得着”
数据库·sql·程序人生·云原生·运维开发·学习方法·dba
专业机床数据采集11 小时前
C# 精雕数控 数据采集 Demo|实时读取精雕机床坐标、主轴、负载、加工工时全量参数
网络·网络协议·tcp/ip·mes·精雕数控数据采集
张忠琳16 小时前
【kubevirt】(virt-launcher Part 6)virt-launcher 设备/网络/存储/外设层
云原生·架构·kubernetes·kubevirt
发光小北16 小时前
双通道 CAN (FD) 转以太网如何应用?
网络协议
汤愈韬18 小时前
四种 NAT 类型详解|透彻理解 NAT 穿越原理(全锥 / 受限锥 / 端口受限锥 / 对称 NAT)
网络·网络协议·安全·网络安全·security
酉鬼女又兒19 小时前
零基础入门计算机网络:第一章概述全解(三种交换方式+八大性能指标+体系结构分层+十年考研真题精讲)
网络协议·计算机网络·考研·网络安全·职场和发展·计算机外设·求职招聘
战南诚20 小时前
HTTP 与 HTTPS 的区别:从原理到实战详解
网络协议·http·https