掘金 后端 ( ) • 2024-04-22 20:32

hello,大家好,我是张张,「架构精进之路」公号作者。

要了解gRPC,就不得不提RPC,所以上手 gRPC 之前,我们需要先搞懂什么是 RPC。

废话不多啰嗦,直接开始吧~

一、RPC

1.1 什么是 RPC ?

RPC 的全称是 Remote Procedure Call Protocol,中文名是远程过程调用协议

RPC 框架的目标就是让远程服务调用更加简单、透明,其负责屏蔽底层的传输方式(TCP/UDP)、序列化方式(XML/Json)和通信细节,让远程服务调用更加简单、透明。

举个栗子:

两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

其实你可以这么理解:

  • RPC 是一种协议

  • RPC 是一种 Client/Server 的传输模式

官方的描述是:一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。

1.2 为什么要用 RPC ?

就是无法在一个进程内,甚至一个计算机内通过本地调用的方式完成的需求,比如比如不同的系统间的通讯,甚至不同的组织间的通讯。由于计算能力需要横向扩展,需要在多台机器组成的集群上部署应用。

我们急需一种高效的应用程序之间的通讯手段来完成这种需求,RPC 大显身手的时候来了!

RPC 的协议有很多,比如最早的CORBA,Java RMI,Web Service的RPC风格,Hessian,Thrift,甚至Rest API。

1.3 RPC 的应用场景

一般常应用在这两个场景:

  • 实时聊天

  • 微服务系统

1.4 RPC 的传输过程

RPC 的传输过程是怎样的呢?

  • 调用者(客户端 Client)以本地调用的方式发起调用;

  • Client stub(客户端存根)收到调用后,负责将被调用的方法名、参数等打包编码成特定格式的能进行网络传输的消息体;

  • Client stub将消息体通过网络发送给服务端;

  • Server stub(服务端存根)收到通过网络接收到消息后按照相应格式进行拆包解码,获取方法名和参数;

  • Server stub 根据方法名和参数进行本地调用;

  • 被调用者(Server)本地调用执行后将结果返回给 server stub;

  • Server stub 将返回值打包编码成消息,并通过网络发送给客户端;

  • Client stub 收到消息后,进行拆包解码,返回给 Client;

  • Client 得到本次 RPC 调用的最终结果。

通过上述流程,RPC 主要分为三层:

  • 用户和服务器(负责处理业务逻辑,调用本地 Stub)

  • Stub 处理客户端和服务端约定好的语法、语义的封装和解封装

  • RPCRuntime 负责最底层的网络传输

二、gRPC

2.1 gRPC 是什么?

gRPC 是一个高性能、通用的开源 RPC 框架,基于 HTTP2 协议标准设计开发,默认采用 Protocol Buffers 数据序列化协议,支持多种开发语言。

常见 gRPC 的应用场景,主要侧重于后端服务之间进行调用。

gRPC 的组成部分:

  • 使用 http2 作为网络传输层

  • 使用 protobuf 这个高性能的数据包序列化协议

  • 通过 protoc gprc 插件生成易用的 SDK

2.2 使用 http2 协议

为什么会选用 http2 作为 gRPC 的传输协议?

除了速度之外,最大的原因就是最大程度的服务兼容性。因为 gRPC 基于 http2 协议,加之市面上主流的代理工具也都支持 http2 协议,所以自然就支持 gRPC 了。

gRPC 的优点自然也包含了HTTP2 的优点:

  • 数据传输二进制分帧

  • 多路复用

  • 服务端推送

  • 头部压缩

2.3 RPC 的使用场景

随着微服务的不断发展,基于语言中立性的原则构建微服务,逐渐成为一种主流设计模式。

例如对于后端并发处理要求高的微服务,比较适合采用 Go 语言构建,而对于前端的 Web 界面,则更适合 JavaScript。

因此,基于多语言的 gRPC 框架来构建微服务,是一种比较好的技术选择。

  • gRPC Microservice

  • gRPC Kubernetes

2.4 gRPC 是怎么传输的?

在 gRPC 中,客户端应用程序可以像本地对象一样直接调用不同机器上的服务器应用程序上的方法,从而使您更轻松地创建分布式应用程序和服务。与许多 RPC 系统一样,gRPC 基于定义服务的思想,指定可以远程调用的方法及其参数和返回类型。在服务器端,服务器实现这个接口并运行一个gRPC服务器来处理客户端调用。在客户端,客户端有一个存根(在某些语言中简称为客户端),它提供与服务器相同的方法。

从上图和文档中可以看出,用 gRPC 来进行远程调用服务,客户端( client ) 仅仅需要 gRPC Stub (为啥叫存根?) ,通过 , Request 向 gRPC Server 发起服务调用,然后 gRPC Server 通过 Proto Response(s) 将调用结果返回给调用的 client。

2.5 关于协议缓冲区(protocol buffers)

Protocol Buffers ( Protobuf ) 是一种免费开源的跨平台数据格式,用于序列化结构化数据。对于开发通过网络相互通信或存储数据的程序很有用。

它是一种数据表达方式,以 .proto 结尾的数据文件,我们可以将其类比为 json、xml 等文件。

其优点在于,编解码速度更快且传输的数据更小。

Protocol Buffers 的优点:

  • 性能好/效率高:时间和空间开销较少

  • 有代码生成机制:protobuf可以自动生成它的.h 文件和点.cpp文件。protobuf将对结构体testA的操作封装成一个类

  • 支持向后兼容和向前兼容:当客户端和服务器同事使用一块协议的时候, 当客户端在协议中增加一个字节,并不会影响客户端的使用

  • 支持多种编程语言:在Google官方发布的源代码中包含了c++、java、Python三种语言

Protobuf 的缺点:

  • 二进制格式导致可读性差

为了提高性能,protobuf采用了二进制格式进行编码。这直接导致了可读性差。这个直接影响开发测试时候的效率。当然,一般情况下,protobuf非常可靠,并不会出现太大的问题。

  • 缺乏自描述

一般来说,XML是自描述的,而protobuf格式则不是。 给你一段二进制格式的协议内容,不配合你写的结构体是看不出来什么作用的。

  • 通用性差

protobuf虽然支持了大量语言的序列化和反序列化,但仍然并不是一个跨平台和语言的传输标准。在多平台消息传递中,对其他项目的兼容性并不是很好,需要做相应的适配改造工作。相比json 和 XML,通用性还是没那么好。

·END·

希望今天的讲解对大家有所帮助,谢谢!

Thanks for reading!

作者:架构精进之路,十年研发风雨路,大厂架构师,CSDN 博客专家,专注架构技术沉淀学习及分享,职业与认知升级,坚持分享接地气儿的干货文章,期待与你一起成长。
关注并私信我回复“01”,送你一份程序员成长进阶大礼包,欢迎勾搭。