背景

什么是RPC

  • 远程服务调用,不同服务封装再方法中,可能不在一个机器(分布式),要想像调用本地方法一样调用远程方法。
  • 通过序列化与反序列化进行传输。
  • 广义上:所有调用本程序外的,都可归为RPC,不管是分布式、第三方服务、HTTP接口、还是读写Redis的请求。都不在本地执行。
    • 三个特点:1、约定的语义(接口语法:方法名参数)2、传输通信3、传输内容

RPC与HTTP/HTTP2.0 - 图1

RPC与HTTP/HTTP2.0 - 图2

历史

  • RPC1984就被用来做分布式系统的通信,Java在1.1版本提供了java版本的RPC框架(RMI),而HTTP协议1990年才开始作为主流协议出现,HTTP发明的场景是用于Web架构,而不是分布式系统通信。这导致很长时间里,HTTP都是浏览器程序和后端web系统通信用的东西,上面的文档格式都是HTML(非常啰嗦),RPC才是分布式通信主流。随着AJAX和JSON文档的发展HTTP才摆脱HTML,开始使用JSON这相对简介的文档格式,为后面用于系统间调用顶下基础。
  • 随着RESTful思潮兴起,越来越多系统考虑http提供服务,这是rpc已经是各大分布式的标配了。
  • 但HTTP更普遍,现在大部分系统都是给浏览器使用的。而其中大部分对后端系统间调用的性能要求不高,毕竟都是走内网,他们关系的是前端后端的性能,因此后端调用采用和前端调用一样的技术栈,维护成本低。这是HTTP技术生态也满足,所以http应用广。
  • 一些系统需要RPC;一是老系统;而是对性能要求。

HTTP

RPC实现

RESTful HTTP JSON

RPC与HTTP/HTTP2.0 - 图3

  • RESTful是一种资源状态转换的架构风格,可用来实现PRC。通过HTTP协议传输内容,Header约束编码body大小等,\r\n分割。通过URL和对应参数标示调用的方法和参数,兼容好,易扩展。
  • 缺点:HTTP的Header和json的数据冗余和低压缩率使传输性能差;json难以表达复杂的参数类型,如结构体。
  • HTTP在应用层,通信代价较高。

    RPC

    gRPC HTTP2.0 Protobuf

  • 性能和版本兼容做了提升和让步

    • Protobuf进行数据编码,提高数据压缩率。(C++开发的跨语言、二进制编码的数据序列化协议,超高压缩率,和早期RPC一样需要双方维护一个协议约束文件。)

      C++开发的跨语言、二进制编码的数据序列化协议,超高压缩率,和早期RPC一样需要双方维护一个协议约束文件。 对于JSON等文本形式序列化协议,有几十倍空间和性能提升,如123,文本类需要三个字节(ascii 31 32 33),二进制类只需要一个字节(01111011)。

    • HTTP2.0弥补了HTTP1.0的不足。

      HTTP2.0做了改进,HTTP1.0虽然引入了KeepAlive复用TCP连接,仍有很多问题。 使用KeepAlive的请求是串行执行(非pipeline时),pipeline时有对首阻塞问题。 每次都需要发送不必要的Header。 不能双向通信。 pipeline:HTTP1.1中允许多个请求复用连接,同时可以一口气将请求全部发出去,不用一个返回后再发送第二个,提升并发性。而服务端需要将请求的结果,按照pipeline中发送的顺序进行顺序返回,如果靠前的请求阻塞了,那么靠后请求返回就会被动等待。

    • 同样在调用方和服务方使用协议约定文件,提供参数可选,为版本兼容留下缓冲空间。

RabbitMQ

  • 一般mq交互场景时发布或消费消息,单向过程,rpc是同步的双向交互。mq实现rpc可从三个抽象特点(语义、传输、内容格式)出发。

    • 如何协商调用语义

      mq消息是exchange分发到queue中,消费端在特定的queue中获取,rpc请求依然走这条:方法调用->exchange->queue->方法执行。 创建一个direct类型的exchange,让每个rpc方法对应一个queue,这个exchange通过routing_key分发到对应的queue中,让特定消费者实际执行rpc方法。这样rpc语义就通过queue来约定,而方法的参数,可放入消息中。

    • 如何将结果传递回客户端

      方法调用->exchange``->queue``->方法执行,这条路是单行道,方法执行端执行完rpc方法后不能按照原路将结果返回给客户端。要实现结果回传,就得再开辟一条:结果回传端->exchange``->queue``->结果等待端路径,一条发送prc请求,一条回传rpc结果,方法调用者和方法执行者都会扮演生产者和消费者。 RPC与HTTP/HTTP2.0 - 图4 rbmq中有回调队列(Callback queue)来实现调用结果回传,同时有关联ID(Correlation Id)来标识每一份调用结果。 rpc调用方发送请求时,会在数据中带上回调队列信息(routing_key)和关联ID,执行方执行完后,将关联ID加入执行结果中,并将结果通过exchange发往回调队列(通过routing_key)。rpc调用方在发送请求后,紧接着在设置的回调队列中等结果就行。整个过程(两条路径公用同一个exchange)。 调用参数和调用结果的打包可以用JSON,protobuf等等,协商一致即可。

gRPC与REST

  • REST通常业务为向导,将执行操作映射到HTTP动词,格式简单。通过json数据完成消息通信。不需要中间代理,简化了系统架构。
  • REST弊端:只有请求/响应这种单一的通信方式,对象和字符串之间的序列化操作也影响速度。
  • gRPC是基于二进制流的消息协议,可采用基于Protocol Buffer的IDL定义gRPC API,客户端和服务端使用HTTP/2以Protocol Buffer格式交换二进制消息。
  • gRPC优势:设计复杂更新操作的API非常简单,具有高效紧凑的进程通信机制,在交换大量消息时效率高。客户端和服务端支持多种语言编写。
  • 不足:不方便与JS集成,某些防火墙不支持该协议。

    网络&协议

    image.png

    JAVA概念图

    RPC与HTTP/HTTP2.0 - 图6