何时使用HTTP请求而不是WebSocket(HTTPS2.0)

When to use a HTTP call instead of a WebSocket (or HTTP 2.0)

  linkthis    2018-05-13    3490 words

TL;DR TL;DR TL;DR

在你的项目中,明确何时采用HTTP请求/响应或WebSockets并不容易,无论是UWP还是其它程序;当你在同时面对项目/应用程序中的其他重要决策时这点尤为突出。为了一些明晰的帮助(至少是对此决策),今天的博客会比较HTTP请求( REST )和WebSocket通信,并提供一些你可以遵循的一般性指导。这种指导是一般性的,并不是泾渭分明的,也可能存在最符合实际客户要求与情景的技术违背这一一般性指导的情况。对于开发人员,我们建议采用你的最佳判断。
你可能会怀疑一件事情:为什么不是HTTP 2.0?HTTP 2.0具有双向消息传递的功能,可以用来代替WebSocket,具体情况取决于如何使用,但必须遵循请求/响应模式。Stack Overflow对于HTTP 2.0与WebSockets有不错的讨论。除此之外,尽管UWP支持HTTP 2.0 ,其他客户端也可能不支持,其取决于是哪些人使用你的服务。 因此,使用HTTP 2.0会让许多应用程序支持的客户端数量减少。

TL;DR

一般来说,在做出决定时应遵循以下两个原则:

  • 假设你的API默认使用传统HTTP
  • 查看下面的指导并尝试说服你自己:API应该使用WebSocket

为了快速、直观地比较两者,请看我们的TL;DR图表:

HTTP WebSocket
半双工 全双工
请求响应模式 双向通信模式
Service Push非原生支持
在客户端轮询或流媒体下载技术中使用
Service Push为核心特性
每次请求/连接均有中等程度的开销 保持/建立连接需中等程度的开销
之后每条消息开销极小
中间/边界缓存为核心特性 不可能支持中间/边界缓存
广泛的客户端支持 仅现代浏览器/语言支持

HTTP更好

在评估HTTP是否是更好的选择时,你可能会发现根据场景进行思考会很有帮助。当涉及到场景时,你会发现这些场景特别适合HTTP。

检索资源

客户需要资源的当前状态,而不需要或要求持续更新。例如:足球迷想要查询比赛结果。如果这场比赛在上周举行,则比赛结果将保持不变,并且不太可能有额外的更新。在这种情况下,HTTP将是一个很好的选择。但是,如果这场目前正在进行,就不是这样。对于正在进行的比赛,分数会不断变化并频繁更新。在这种情况下,WebSocket可能是更好的选择。

高度缓存资源

当资源的状态很少改变或者有多个客户端需要检索资源时,其将从缓存中受益。这里是故意使用了“很少”一词,因为它必须根据预期中的客户访问模式来判断,而不是一段固定的时间内的状态。如果频繁更新的资源经常被检索,其可能仍然具有高度的可缓存性,特别是在多客户的情况下。请注意,WebSocket在设计上不允许直接理缓存消息,包括透明代理,因为这可能会降低客户端的性能。

例如:前一周足球比赛的比分可以进行高度缓存,因为它们固定且不太可能改变,所以HTTP非常适合。但是,进行中的足球比赛的比分可能会频繁变化。在这种情况下,资源不能高度缓存,所以WebSocket更适合。

幂等性和安全性

众所周知,HTTP模式具有幂等性和安全性。如果一个请求是“幂等的“,则可以多次发送且不产生唯一的结果。该特性使客户能够以简单的方式应对超时或瞬时网络问题。如果请求不修改正在执行的资源,则该请求是“安全”的。此特性是启用缓存(或预取)的关键。为应对通信故障进行弹性设计时,安全性和幂等性是必须的关键因素。HTTP非常适合这种情况,因为HTTP模式具有广泛的安全性和幂等性期望。WebSocket协议将这些问题留给消息传递层来设计(这意味着没有广泛的行业标准)。

错误状态

请求-响应消息模式是HTTPS设计的核心,这意味着它对错误状态有完善的支持。HTTP在设计上允许响应描述请求或资源的错误,或者对成功状态返回详细的描述以便进行区分。WebSocket协议仅为会影响建立连接的错误状态提供支持。一旦建立连接并开始交换消息,必须在消息传递层中进行设计以解决其余全部错误状态。

同步事件

请求-响应模式非常适合需要同步或者必须以序列化方式执行的操作。对特定请求,HTTP响应有明确的返回,从而保证后续操作能自动化处理。在WebSocket中,这个内容属于消息层设计。在任何形式上,WebSocket协议均不支持对消息的确认。但是在你的设计中,你应该尽量避免这样的假设:客户能一直完美地同步他们的行为。你应该尽量提供无状态交互模式,或者客户端可以进行并行请求,因为这会使你的应用程序在面对不可避免的网络问题或客户端的错误行为时更有弹性。

WebSocket更好

就像HTTP一样,你会发现WebSocket也有自己的适合的场景,此时它可能是您项目的最佳选择。但是,请记住我们在本博客开始时的谨慎态度,因为以下指南未考虑任何特殊消息协议。

快速响应

当客户需要变化更做出快速反应(特别是无法预测的变化)时,WebSocket可能是最好的。假设有一个允许多个用户实时聊天的聊天应用程序。如果使用WebSocket,则每个用户都可以实时发送和接收消息。与REST相比,WebSocket有更高的效率,因为其没有收发每个消息时的HTTP请求/响应开销。

持续更新

通常情况下,当客户希望持续更新资源状态时,WebSockets很适合。当客户无法预测何时会发生变化并且短期内可能发生变化时,WebSockets尤其合适。另一方面,如果客户可以预测变化发生的时间或者它们是否发生变化很少出现,那么HTTP更好—例如,每小时更改一次资源或仅在与其相关资源被修改后才更改的资源。如果客户不知道相关资源已被修改(例如,因为其他客户修改了它,或者服务修改了它),那么WebSockets就更适合了。

及时消息

WebSocket协议不是以请求-响应为核心设计的。消息随时可能从任一连接端发出,并且没有本地支持来表明一条消息与另一条消息关联性。这使得该协议非常适合“阅后即焚”的消息传递场景,而不适合于事务性需求。如果需要的话,你应用必须在消息传递层满足事务性需求。

低负载高频率通信

WebSocket协议提供了一个持久连接来交换消息。这意味着个人信息不会产生任何用以建立连接的额外开销。连接建立开销,如SSL连接、内容协商和大量响应头交换等,仅会在第一次建立连接时产生。每次消息交换几乎没有开销。另一方面,尽管HTTP v1.1有可能允许多个请求重用单次连接,但通常会以很短的超时时间来控制资源开销。由于WebSocket是专门为长期连接场景设计的,其避免了建立连接和发送HTTP请求/响应头的开销,从而显着提高了性能。但是,其不应该用于极端情况。如果仅发送少量消息或消息很少,则应避免使用WebSockets。除非客户必须快速响应或根据更新采取行动,否则保持开放连接可能会导致不必要的资源浪费。

你可能做错了,如果……

可能错误地使用了HTTP,如果……

  • 你的设计依赖于客户端经常发起的轮询服务,而不是用户行为
  • 你的设计需要频繁的服务请求以发送短消息
  • 客户需要对资源的更改快速做出反应,并且无法预测更改发生的时间
  • 由此产生的设计成本过高。问问自己:WebSocket解决方案是否大大减少了设计、实现、测试实行的工作量?

如果出现以下情况,你可能错误地使用WebSockets:

  • 该连接仅被非常少量的事件使用或使用时间很短,客户端不需要对事件做出快速响应
  • 你的功能需要多个WebSocket在同一时间向一个服务开放
  • 你的功能会重复:打开一个WebSocket,发送消息,然后关闭它这一过程
  • 由此产生的设计成本过高。 问问自己:HTTP解决方案是否大大减少了设计、实现、测试和实行作的工作量?

总结

在一开始,我们建议你假设你的API默认使用传统HTTP,除非此博客中的指导让你确信WebSockets是更好的选择。也就是说,这个指导是一般性的,而不是定式。就像一个项目有许多面一样,可能最终最适合你的技术不会总是一般性的指导建议。
其它有关UWP使用HTTP和WebSocket的文档:

由于本人过于咸鱼,不免出现错翻的情况,附上原文链接 When to use a HTTP call instead of a WebSocket (or HTTP 2.0)
本文采用CC BY-NC-ND 4.0许可协议进行许可,转载请注明出处。

本文最后更新时间为:2019-03-03-Sunday-11:14:03 AM




Image of Wechat