前言

HTTP1.0 & HTTP1.1 & HTTP2.0 & RPC

  • HTTP1.0

  • 无法复用连接

HTTP1.0 协议时,HTTP 调用还只能是短链接调用,每次发送请求的时候,都需要进行一次TCP的连接,而TCP的连接释放过程又是比较费事的。这种无连接的特性会使得网络的利用率非常低。

  • 队头阻塞(Head-Of-Line Blocking)

下个请求必须在前一个请求返回后才能发出,request-response按序发生。显然,如果某个请求长时间没有返回,那么接下来的请求就全部阻塞了。

  • HTTP1.1

  • 优点

  • 长连接

HTTP/1.1增加了一个Connection字段,通过设置Keep-Alive可以保持HTTP连接不断开,避免了每次客户端与服务器请求都要重复建立释放建立TCP连接,提高了网络的利用率。

  • 管线化(pipeline)

HTTP 管线化是将多个 HTTP 请求整批提交的技术,而在传送过程中不需先等待服务端的回应。但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回,所以还是有队头阻塞的问题。

  • 缓存控制

  • chunked 编码传输

  • 缺点

  • 队头阻塞

虽然HTTP1.1 引入了pipeling,但 pipeling 要求返回是按序的,那么前一个请求如果很耗时(比如处理大图片),那么后面的请求即使服务器已经处理完,仍会等待前面的请求处理完才开始按序返回。

  • 协议开销大

header里携带的内容过大,在一定程度上增加了传输的成本

:authority: render.com
:method: GET
:path: /p/alertserver/589c123e2b89c03d127000da_config/index.json
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9
if-none-match: W/"12d8-AlMoGNV3gJOfKIoHdgvIIv9I95M"
origin: https://baidu.com
referer: https://baidu.com/
sec-ch-ua: "Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
  • 传输内容是明文,不够安全

  • keep-alive 给服务端带来性能压力

  • HTTP2.0

  • header压缩

HTTP1.1的头部是冗余的,HTTP2.0协议会采用合适的压缩算法压缩HTTP请求和响应的首部。这样,通信产生的数据包数量和发送的字节数就更少了。在应用层与传输层之间添加一层二进制分帧层。HTTP2.0是二进制协议,他采用二进制格式传输数据而不是1.x的文本格式。文本格式可读性好,但是对计算机解析不友好。

HTTP1.x中采用文本格式传输,每个传输会增加500~800字节的开销。每次请求都要带上向cookie、user-agent这样相同的首部。HTTP采用HPACK压缩双来压缩头部。在浏览器与服务器之间:

  1. 维护一份相同的静态字典,包含常见的头部名称,以及常见的头部值

  1. 维护一份相同的动态字典,可以动态的添加内容

  1. 通过静态Huffman编码对传输的首部字段进行编码

所以我们在传输首部字段的时候,例如要传输method:GET,我们只要传输静态字典里面的method:GET对应的索引值就可以,一个字节就搞定了。假如像user-agent、cookie这种静态字典里面只有首部名称而没有值的首部,第一次传输需要在静态字典中加入值,值会采用静态Huffman编码来减小体积。第一次传输过user-agent之后,浏览器和服务器就会把它添加到自己的动态字典 中,后续的传输就可以只传输一个索引就行了。

  • 多路复用(multiplexing)

HTTP2.0建立一个TCP连接,一个连接上面可以有任意多个流,消息分割成一个或多个帧在流里面传输。帧传输过去之后,在进行重组,形成一个完整的请求和响应。Steam是乱序的,但同一个Sream里面的帧是按序传输的,二进制帧到达后,对方将Sream ID相同的二进制帧组装成完整的请求报文 和响应报文,通过单一的TCP连接,可以无限制处理多个HTTP请求

  • 请求优先级(request priorityzation)

HTTP2.0不仅可以无限制的并发处理请求,还可以给请求逐个分配优先级顺序。这样重要的请求就会优先响应。

  • RPC

Remote Procedure Call,远程过程调用,RPC只是一种调用方式

  • 通信协议

可以基于TCP,也可以基于HTTP,所以通信协议上和HTTP 没有什么区别,甚至HTTP也可以看做是一种RPC,比如基于HTTP2.0的gRPC

  • 序列化协议

  • HTTP1.1

基于文本编码的xml、json序列化协议

  • HTTP2.0

基于二进制编码的protobuf

  • RPC

基于二进制编码的自定义协议:protobuf、hessian、dubbo等

HTTP1.1

HTTP2.0

RPC

OSI模型

应用层协议(7层)

传输层协议(4层)

传输内容

效率

连接方式

长连接

长连接

序列化协议

JSON/XML

Protocol Buffers

Protocol Buffers,hessian、kyro

序列化方式

文本类

二进制

二进制

小结

序列化协议我们不选择JSON/XML,而是选择标准的Protobuf,或者自定义的协议。

https://auth0.com/blog/beating-json-performance-with-protobuf/

常用的RPC框架

  • SpringCloudOpenFeign

  • Dubbo

  • gRpc

  • Thrift

SpringCloudOpenFeign

基于HTTP1.1的,简单易用,但是性能不够高,我们不考虑。

Dubbo

介绍

Dubbo是一个高性能、轻量级RPC框架,官网现在已定义为微服务框架,目的就是让消费方、生产方通过服务注册、服务发现、服务调用实现动态通信。

官方介绍除了服务注册、调用,还提供可视化监听运维、服务容错、服务降级等其它扩展功能

默认就是走dubbo协议的,单一长连接,NIO异步通信,基于hessian作为序列化协议。

适用的场景:传输数据量很小(每次请求在100kb以内),但是并发量很高的长连接。

调用流程

负载均衡

  • RandomLoadBalance 随机调用负载均衡

  • RoundRobinLoadBlance 轮询调用

  • LeastActiveLoadBlance 最少活跃数调用法

  • ConsistentHashLoadBalance 一致性Hash算法

容错机制

  • Failover

失败自动切换,当出现失败,重试其它服务器。(缺省) 通常用于读操作,但重试会带来更长延迟。可通过retries="2"来设置重试次数(不含第一次)。

<dubbo:service retries="2" />

  • 快速失败

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

<dubbo:service cluster="failfast" />

  • Failsafe

失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作。

<dubbo:service cluster="failsafe" />

  • FailbackCluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

  • ForkingCluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数。

<dubbo:servicecluster=“forking" />

  • Broadcast

广播调用所有服务端,逐个调用,任意一台报错则报错,通常用于更新本地方法,比如:清除本地缓存

gRpc

介绍

gRPC 是一个高性能、通用的开源 RPC 框架,其由 Google 2015 年主要面向移动应用开发并基于 HTTP/2 协议标准而设计,基于 ProtoBuf 序列化协议开发,且支持众多开发语言。

由于是开源框架,通信的双方可以进行二次开发,所以客户端和服务器端之间的通信会更加专注于业务层面的内容,减少了对由 gRPC 框架实现的底层通信的关注。

如下图,DATA 部分即业务层面内容,下面所有的信息都由 gRPC 进行封装。

调用流程

客户端(gRPC Stub)调用 A 方法,发起 RPC 调用。

对请求信息使用 Protobuf 进行对象序列化压缩(IDL)。

服务端(gRPC Server)接收到请求后,解码请求体,进行业务逻辑处理并返回。

对响应结果使用 Protobuf 进行对象序列化压缩(IDL)。

客户端接受到服务端响应,解码请求体。回调被调用的 A 方法,唤醒正在等待响应(阻塞)的客户端调用并返回响应结果。

gRpc的特点

优点

protobuf二进制消息,性能好/效率高

proto文件生成目标代码,简单易用

序列化反序列化直接对应程序中的数据类,不需要解析后在进行映射

支持向前兼容和向后兼容

支持多种语言,底层采用Netty实现

缺点

GRPC尚未提供链接池,需要自己实现。

尚未提供服务发现、负载均衡机制

Protobuf二进制可读性差

什么是Protocol Buffers?

你可以理解ProtoBuf是一种更加灵活、高效的数据格式,与XML、JSON类似,在一些高性能且对响应速度有要求的数据传输场景非常适用。ProtoBuf在gRPC的框架中主要有三个作用:

  • 定义数据结构

  • 定义服务接口

  • 通过序列化和反序列化,提升传输效率

为什么ProtoBuf会提高传输效率呢?

我们知道使用XML、JSON进行数据编译时,数据文本格式更容易阅读,但进行数据交换时,设备就需要耗费大量的CPU在I/O动作上,自然会影响整个传输速率。Protocol Buffers不像前者,它会将字符串进行序列化后再进行传输,即二进制数据。

可以看到其实两者内容相差不大,并且内容非常直观,但是Protocol Buffers编码的内容只是提供给操作者阅读的,实际上传输的并不会以这种文本形式,而是序列化后的二进制数据。字节数会比JSON、XML的字节数少很多,速率更快。

如何支撑跨平台,多语言呢?

Protocol Buffers自带一个编译器也是一个优势点。前面提到的proto文件就是通过编译器进行编译的,proto文件需要编译生成一个类似库文件,基于库文件才能真正开发数据应用。具体用什么编程语言编译生成这个库文件呢?由于现网中负责网络设备和服务器设备的运维人员往往不是同一组人,运维人员可能会习惯使用不同的编程语言进行运维开发,那么Protocol Buffers其中一个优势就能发挥出来——跨语言。

从上面的介绍,我们得出在编码方面Protocol Buffers对比JSON、XML的优点:

  • 简单,体积小,数据描述文件大小只有1/10至1/3;

  • 传输和解析的速率快,相比XML等,解析速度提升20倍甚至更高;

  • 可编译性强。

基于HTTP 2.0标准设计

除了 Protocol Buffers 之外,从交互图中和分层框架可以看到, gRPC 还有另外一个优势——它是基于 HTTP 2.0 协议的。

由于 gRPC 基于 HTTP 2.0 标准设计,带来了更多强大功能,如多路复用、二进制帧、头部压缩、推送机制。

这些功能给设备带来重大益处,如节省带宽、降低 TCP 连接次数、节省 CPU 使用等,gRPC 既能够在客户端应用,也能够在服务器端应用,从而以透明的方式实现两端的通信和简化通信系统的构建。

HTTP 1.X 定义了四种与服务器交互的方式,分别为 GET、POST、PUT、DELETE,这些在 HTTP 2.0 中均保留,我们看看 HTTP 2.0 的新特性:双向流、多路复用、二进制帧、头部压缩。

Thrift

介绍

thrift是一种可伸缩的跨语言服务的RPC软件框架。它结合了功能强大的软件堆栈的代码生成引擎,以建设服务,高效、无缝地在多种语言间结合使用。2007年由facebook贡献到apache基金,是apache下的顶级项目,具备如下特点:

  • 支持多语言:C、C++ 、C# 、D 、Delphi 、Erlang 、Go 、Haxe 、Haskell 、Java 、JavaScript、node.js 、OCaml 、Perl 、PHP 、Python 、Ruby 、SmallTalk

  • 消息定义文件支持注释,数据结构与传输表现的分离,支持多种消息格式

  • 包含完整的客户端/服务端堆栈,可快速实现RPC,支持同步和异步通信

Thrift框架结构

Thrift是一套包含序列化功能和支持服务通信的RPC(远程服务调用)框架,也是一种微服务框架。其主要特点是可以跨语言使用,这也是这个框架最吸引人的地方。

图中code是用户实现的业务逻辑,接下来的 Service.Client和 write()/read()是thrift根据IDL生成的客户端和服务端的代码,对应于RPC中Client stub和Server stub。TProtocol 用来对数据进行序列化与反序列化,具体方法包括二进制,JSON 或者 Apache Thrift 定义的格式。TTransport 提供数据传输功能,使用 Apache Thrift 可以方便地定义一个服务并选择不同的传输协议。

Thrift网络栈结构

thirft使用socket进行数据传输,数据以特定的格式发送,接收方进行解析。我们定义好thrift的IDL文件后,就可以使用thrift的编译器来生成双方语言的接口、model,在生成的model以及接口代码中会有解码编码的代码。thrift网络栈结构如下:

Transport层

代表Thrift的数据传输方式,Thrift定义了如下几种常用数据传输方式:

TSocket: 阻塞式socket;

TFramedTransport: 以frame为单位进行传输,非阻塞式服务中使用;

TFileTransport: 以文件形式进行传输。

TProtocol层

代表thrift客户端和服务端之间传输数据的协议,通俗来讲就是客户端和服务端之间传输数据的格式(例如json等),thrift定义了如下几种常见的格式:

TBinaryProtocol: 二进制格式;

TCompactProtocol: 压缩格式;

TJSONProtocol: JSON格式;

TSimpleJSONProtocol: 提供只写的JSON协议。

Server模型

  • TSimpleServer: 简单的单线程服务模型,常用于测试;

  • TThreadPoolServer: 多线程服务模型,使用标准的阻塞式IO;

  • TNonBlockingServer: 多线程服务模型,使用非阻塞式IO(需要使用TFramedTransport数据传输方式);

  • THsHaServer: THsHa引入了线程池去处理,其模型读写任务放到线程池去处理,Half-sync/Half-async处理模式,Half-async是在处理IO事件上(accept/read/write io),Half-sync用于handler对rpc的同步处理;

对比

SpringCloudOpenFeign

Dubbo

gRpc

Thrift

Conpany

Spring

Alibaba

Google

Facebook

Apache

跨语言

Java

Java

跨语言

跨语言

通讯协议

Dubbo协议(走Hessian序列化,单一长连接,NIO异步通信,传输数据量很小,但是并发量很高的长连接)

Rmi协议(走java二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输,一般较少用)

Hessian协议(走Hessian序列化,多个短连接,适用于提供者数量比消费者数量还多,适用于文件的传输,一般较少用)

HTTP协议(走json序列化,一般较少用)

Dubbo Thrift协议

Redis协议...

HTTP2.0协议

TSocket(使用堵塞式I/O进行传输,也是最常见的模式)

TFramedTransport(使用非阻塞方式,以frame为单位进行传输,类似于Java中的NIO)

TFileTransport(以文件形式进行传输,虽然这种方式不提供Java的实现,但是实现起来非常简单)

TMemoryTransport(使用内存I/O,如Java中的ByteArrayOutputStream实现)

TZlibTransport(使用执行zlib压缩,与其他传输方式联合使用,不提供Java的实现)

TNonblockingTransport(使用非阻塞方式,用于构建异步客户端)

序列化

Hessian

Json

ProtoBuf

TBinaryProtocol(二进制编码格式进行数据传输)

TCompactProtocol(高效密集型的二进制序列化协议,使用Variable-Length Quantity (VLQ) 编码对数据进行压缩)

TJSONProtocol(使用JSON的数据编码协议进行数据传输)

TSimpleJSONProtocol(只提供JSON只写的协议,适用于通过脚本语言解析)

负载均衡

Random

RoundRobin

ConsistenHash

LeastActive

容错机制

Failover

Failfast

Failsafe

Failback

Forking

Broadcast

Failover

服务注册与服务发现

Zookeeper

Redis

Multicas

Simple

性能

★★

★★★

★★★★

性能测试

吞吐率

rpcx > thrift > gRpc > Motan > Dubbo

平均响应时间

rpcx > thrift > gRpc > Motan > Dubbo

但是这个是平均响应时间,可能掩盖一些真相,尤其是当响应时间的分布不是那么平均,所以我们还可以关注另外一个指标,就是中位数(所谓中位数的意就是把将一组数据按大小顺序排列,处在最中间位置的一个数叫做这组数据的中位数

,这意味着至少有50%的数据低于或高于这个中位数)。

这里的中位数指小于这个数值的测试数和大于这个数值的测试数相等。

中位数

gRpc > thrift > rpcx > Motan > Dubbo

极端情况

rpcx > Motan > thrift > gRpc > Dubbo

gRpc & thrift

https://github.com/chrislee87/rpc_benchmark

个人总结

  • RPC最主要的就是性能

  • SpringCloudOpenFeign是基于HTTP1.1协议文本类Json序列化格式的,性能低,排除。

  • Dubbo现在已经成为了服务治理的微服务框架,负载均衡与容错机制很完善,但是性能低于gRpc和Thrift。而且我们使用K8S容器来做服务注册与发现,K8S也已经包含了负载均衡的功能,所以我们排除Dubbo。

  • thrift 是Software framework for scalable cross-language services development,性能也很强劲,也可以与非常多的语言无缝结合,很适用于跨语言的服务开发,技术出来的很早,现在社区不够活跃,文档非常的少。

  • gRpc is a modern open source high performance RPC framework that can run in any environment. 在github的社区上更加活跃,Protocol buffer (Protobuff) serializes very quickly on the server and client. Protobuff serialization results in small message payloads,而且Protobuff协议已经成为了业界的标准,所以我们选择 gRpc。

【云原生】RPC技术选型相关推荐

  1. 虎年云原生落地技术趋势

    今天是立春,虎年第一天.去年我写过一篇 牛年 dotnet云原生技术趋势[1],今天再来写一篇虎年云原生落地技术趋势,去年局限在.NET 平台上的云原生落地,我今年在去年探索云原生落地的基础上从多语言 ...

  2. 分布式,集中式,云原生存储技术

    分布式,集中式,云原生存储技术 分布式存储软件是真正的统一存储,实现同一套存储系统为上层应用提供块.文件和对象三种数据服务,满足业务对结构化和非结构化数据的存放需求,内置数据保护功能,例如:备份.容灾 ...

  3. 广州站 | 云原生 Serverless 技术实践营精彩回顾

    12月2日,由阿里云 Serverless 团队主办的「云原生 Serverless 技术实践营」在广州顺利举行,本次活动面向所有企业技术人员,主打"沉浸式沙龙体验,6 小时搞定 Serve ...

  4. 云原生火爆技术人朋友圈,你可别云里雾里了!

    扫描上方二维码直达精彩回顾 整理 | 八宝粥,责编 | 伍杏玲,视频 | 王晓曼 出品 | CSDN(ID:CSDNnews) 据 IDC 报告显示,到 2022 年,90% 的新应用将具有微服务架构 ...

  5. 边缘计算云原生开源方案选型比较

    作者 | LanLiang 来源 | https://zhuanlan.zhihu.com/p/353429279?utm_source=wechat_session&utm_medium=s ...

  6. 剑指Kubernetes 揭秘腾讯云的PaaS技术选型策略

    点击关注 InfoQ,置顶公众号 接收程序员的 8 点技术早餐 1 前言 Kubernetes 很火,一大批互联网公司早已领先一步,搭建起专有的 PaaS平台,传统企业们看到的 Kubernetes的 ...

  7. 云原生存储工具的选型和应用探讨

    Labs 导读 随着云原生概念在业界的推广,传统应用部署的方式被容器化部署所取代.基于云原生的容器化部署和运维,给开发和运维人员带来DevOps快速部署和自动化运维等诸多便利的同时,对于基础架构服务也 ...

  8. 精华总结 |「跨越疫情之境,迈向新的征程」盘点一下2022年度我们开发团队对于云原生的技术体系的变革历程

    云原生发展历程 「2022年已过去,最开心的两件事」 「盘点2022年的其他的重大的事件」 「直奔主题-云原生的改革之路」 [Kubernetes的版本升级] 版本升级大纲 升级版本 升级版本的必要性 ...

  9. 从虚拟化到云原生——容器技术的发展史

    近年来,云原生 (Cloud Native)可谓是 IT 界最火的概念之一,众多互联网巨头都已经开始积极拥抱云原生.而说到云原生,我们就不得不了解本文的主角 -- 容器(container).容器技术 ...

  10. 云原生年度技术盘点出炉,乘风破浪正当时

    2021年,数字产业蓬勃发展,传统云计算产业走向成熟,大数据.物联网.人工智能.区块链各种新兴技术百花齐放. 云原生已经成为势不可挡的技术趋势.Gartner 预测到 2025 年,95%数字化运维将 ...

最新文章

  1. c++ 重载、重写、重定义(隐藏)
  2. Openstack执行任何操作都反馈是HTTP401解决办法
  3. ajax 的同步和异步
  4. 2017/9/26Codeforces E题
  5. datatype未定义是什么意思_vue.js一直提示未定义
  6. 微软拆分操作系统的计划初现雏形
  7. android学生管理实例,学生管理系统-基于SQLite数据库的Android应用
  8. linux入门怎么学?
  9. 概率语言模型及其变形系列-PLSA及EM算法
  10. 1.13 单用户模式;1.14 救援模式;1.15 克隆虚拟机;1.16 Linux机器相互登录
  11. android 滑动tabhost,tabhost左右滑动按钮
  12. AutoJs学习-图灵QQ自动聊天机器人
  13. 自学python就业_Python就业方向有哪些呀?适合小白学习吗?
  14. Babylongjs-纹理
  15. 一个html文档必须有,创建一个完整的HTML文档总结
  16. Android:适配器刷新数据无效
  17. HADOOP学习详细教程
  18. 添加多浏览器支持是什么意思_低gi什么意思,减肥期间一定要多吃低gi的食物吗?- 理财技巧...
  19. STM32 堆栈大小的设置及分析
  20. POJ 2305大数求余

热门文章

  1. .Net Core MVC引入static静态变量到.cshtml页面
  2. 【人话版】摸着WEB3过河的互联网风景线
  3. 电脑系统数据丢失了是什么原因?找回方法有哪些?
  4. linux运维笔记:动态网页资源
  5. iptables匹配multiport
  6. 装完 Ubuntu 安装常用的软件
  7. 中级软件设计师备考攻略
  8. 嵌入式软件工程师相关的应聘要求
  9. 排课系统matlab,matlab数学建模排课
  10. nc: command not found完美解决(linux配置nc命令)