介绍
在2010年左右,随着互联网络的日益互联,许多开发人员开始围绕RESTful服务进行标准化。 REST提供了一种通过HTTP / 1进行通信的通用方法,传统上它伴随着基于JSON的序列化方案。
2010年中期和后期一直在经历实时网络的出现,尽管REST仍然是连接服务的一种相关方式,但是HTTP / 1和JSON越来越不适合消费者的严格实时数据需求。 已经习惯于使用舒适的,嵌入到语言的HTTP库的开发人员开始意识到需要更合适的东西。 这篇文章将介绍一些常见的替代方案,简要介绍它们之间的相互关系,并探讨未来可能会发生的情况。
- Plex VPN入门指南
- 艺术家需要知道的关于流媒体利润增长44%的5件事
- Orange的音乐,文化和信息娱乐副总裁Laurence Le Ny
- Netflix KontraResztaświata
- 广告与非广告-大分频器
性能
运动场
这里讨论的竞争环境大致由一元协议¹和流协议组成。 我们将讨论的一元协议是HTTP / 1,HTTP / 2上的一元gRPC和UDP²。 我们将研究的流协议是Websocket和基于HTTP / 2的gRPC流。
对于那些尚未学习网络协议的人来说,这是一个小笔记 UDP是第4层协议,而此处介绍的所有其他协议都是基于TCP(第4层)构建的第7层。
设置

为了衡量这些协议,我们将进行从亚洲到中美洲的漫长旅行,并且每个协议发送100,000条消息。 这个架构中的每个应用程序都是用Go编写的,每个发送者同时发送消息。
在发送和接收消息时,我们将记录开始时间,结束时间,并跟踪数据包到达时的计数。 请注意,在许多环境中,依靠不同步的系统时钟会很危险-幸运的是,此设置在Google Cloud上运行,这意味着我们可以利用TrueTime。
没有显示一个准系统前端,该前端系统负责显示进度,并将RequestToSend消息(一些实际消息的存根)推送到pubsub代理中。 我们在世界范围内传输的消息非常小-一个字符串字段和两个时间字段。
输入 SendRequest struct {
RunId字符串`json:“ runId”`
Amount int`json:“ amount”`
}
输入 Message struct {
RunId字符串`json:“ runId”`
SentAt time.Time`json :“ sentAt”`
ReceivedAt time.Time`json :“ receivedAt”`
}
发送100,000条消息

让我们花点时间看一下结果。 与流式同类服务器相比,HTTP / 1.1和一元gRPC爬网这一事实是最重要的,而且可能是最预期的结果。 创建和销毁连接非常昂贵,这里的教训是删除这些操作可以为您的系统带来巨大的性能提升。
在一元协议中,UDP表现出色……但从未完成。 使用UDP的任何人都可能对此结果很熟悉。 UDP是无连接的,没有Acks³的概念。 当TCP消息丢失时,永远不会发生确认,这将导致客户端重试该消息。 在UDP的情况下,消息只是丢失了。 因此,尽管UDP表现良好,但我们应该注意仅将其用于非关键数据(视频流是一个很好的例子)。
在Websocket和流式gRPC之间,此演示没有什么区别。 我们应该选择哪一个? 简短的答案是gRPC。 原因是gRPC建立在HTTP / 2之上,它具有显着的优势,例如报头压缩,在单个连接上多路复用请求以及HTTP / 2使用的二进制协议。 JSON,我们将在另一篇文章中介绍它,并且它有一个强大的负载平衡故事-Websockets传统上一直在努力解决这个问题。
陷阱
考虑到结果,流似乎是一个显而易见的选择。 它是实时的,非常快的并且被广泛采用。 但是,有一个陷阱需要考虑:短期采用。
路由器,NAT,代理,负载均衡器和Internet的其他网络设备根本不普遍支持流连接。 这些物理设备可能配置有规则,这些规则对短暂的TCP消息有意义,但对长期的TCP消息有害。 例如,仅平衡新连接的负载平衡器会与寿命长的连接发生冲突,并且可能会定期终止寿命长的连接以实施新连接。
对于开发人员而言,这意味着有时难以预测的性能和行为难以调试。 它还需要对客户端库的幕后工作有更深入的了解。 有些负责诸如连接池,流量控制和自动重试之类的事情,另一些则要求开发人员实现其中一些功能。
批处理请求的案例
流应该是开发人员工具包中的重要工具,但是存在一种用于传递大量数据的简单替代方法-批处理。 批处理失去了流式传输的实时优势,但是执行得非常好。 如果系统不需要实时性能,则一元协议的批处理请求可能是一元调用的简单性和慢性以及流的复杂性和速度之间的良好中间地带。
全部放在一起
简而言之:
- 一元协议非常适合单请求模式,因为它们很简单。
- 流gRPC正在迅速成为高吞吐量实时系统的标准。
- 如果不考虑实时性,使用一元协议批量处理请求可能是一个不错的选择。
但是,如果没有其他问题,最重要的是应该在开发系统之前仔细考虑所选择的协议。 这些选择是许多设计决策的核心,并且很快就根深蒂固-明智地选择!
未来网
除了这些协议,还针对不同的用例开发了更多协议。 这里有几个值得一试的地方:
- MQTT最初由IBM开发,由于其占地面积极小,因此是物联网应用程序的常见选择。
- AMQP,它倾向于在消息传递服务中找到自己的位置,尤其是在诸如RabbitMQ之类的排队产品上。
- ZeroMQ和Nanomsg; 两个有前途的分布式消息传递系统,专门为快速,高吞吐量的系统而设计,对库应提供的内容有两种不同的理解。
- QUIC是Google图书馆使用的UDP上的多路复用流传输,可加快网络速度。
- Twitch最近发布了twirp,而Facebook发布了Thrift-gRPC的两个直接替代品。
参考和脚注
可以在https://github.com/jadekler/protocol-measurement中找到此演讲的代码。
¹ 倾向于在每个连接上发送一条消息的协议。 一些协议位于灰色区域。 例如,尽管许多内核实现在后台共享连接,但我们将HTTP / 1.1描述为一元的。
²UDP可以说是流,因为它不需要为每次写操作建立新的连接(一旦拨号,便可以重新使用套接字)。 但是,由于UDP不维护连接,因此其行为与一元协议更相似。 更好的分类可能会将UDP放入自己的无连接存储桶中。
³确认收到消息。
⁴https://http2.github.io/faq/