HTTP与WebSocket协议的区别

HTTP请求(REST)与WebSocket通信的主要区别在于工作模式,WebSocket通过单个TCP连接提供全双工通信,所以WebSocket能够将信息直接推送到客户端。

HTTP和WebSocket的区别及使用场景

HTTP和WebSocket的区别

HTTP和WebSocket之间的可视化比较,看看这个TL;DR图表

HTTP和WebSocket的区别

WebSocket是一种通过单个TCP连接提供全双工通信(通道)的协议,而HTTP提供半双工通信。

WebSocket的信息交换模式是双向的,意味着服务器可以将信息直接推送到客户端(HTTP不直接支持)。

HTTP和WebSocket的区别

每个流的内容都是HTTP请求和响应,只是编码和打包方式不同。其中,WebSocket添加了一些特性来管理流,但是保留了旧的语义。

HTTP和WebSocket的区别

如果使用加密的WebSocket连接,那么在WebSocket安全连接中使用Transport Layer Security (TLS),可以确保当浏览器配置为使用显式代理服务器时能够发出HTTP CONNECT命令。

HTTP和WebSocket的区别及使用场景

这将在WebSocket安全客户端和WebSocket服务器之间建立一个隧道,通过HTTP代理提供低级的端到端TCP通信。

HTTP与WebSocket的应用场景

一般来说在做出选择时,请遵循以下两个原则:

假设你的API应该默认为传统HTTP。

查看下面的指导并尝试说服自己,你的API是否应该是WebSocket。

HTTP的应用场景

在评估HTTP是否是更好的选择时,根据场景进行思考会很有帮助,当涉及到以下场景时,会发现HTTP非常适合。

检索资源(Retrieve Resource)

客户端只需要知道资源的当前状态,而不需要(持续)更新,例如:球迷想要知道比赛的结果,如果比赛发生在上周,则游戏结果已定,并且不太可能发生更新。

对于这种场景,HTTP将是一个合理的选择,但是,如果比赛目前正在进行中,则情况就大为不同,对于正在进行的比赛,分数将不断变化,并且频繁更新。在这种情况下,WebSocket可能是更好的选择。

高度可缓存的资源(Highly Cacheable Resource)

当一个资源很少改变或者多个客户端都要对资源检索时,使资源可以从缓存中受益,“很少”一词在这里变得很隐晦,因为它必须根据预期的客户端访问模式来判断,而不是根据固定的时间。

如果频繁检索高度易变的资源,特别是由多个客户端进行检索,那么这些资源仍然具有很高的可缓存性。WebSocket设计不允许显式或透明代理缓存消息,直接影响客户端的性能。

例如:上周足球比赛得分结果高度可缓存,因为它们不太可能发生变化,因此HTTP非常适合。然而,正在进行的足球比赛的得分会可能会经常变化,在这种情况下,资源是高度不可缓存的,因此WebSocket变得更适合。

幂等性和安全性(Idempotency and Safety)

HTTP方法具有的幂等性和安全性众所周知,如果请求可以多次发出而不会影响最终结果,则该请求是“幂等的”。这一特性允许客户端直接处理超时或临时网络问题,如果请求不修改正在执行的资源,则该请求是“安全的”。

此特性是启用缓存(或预取)的关键。采用安全性和幂等性的设计,其根源是必须能够抵御通信故障。HTTP非常适合这种情况,因为HTTP方法广泛地用于对安全性和幂等性有要求的场景。WebSocket协议将这些问题留给了消息传递层(这意味着没有广泛的行业标准支持)。

错误方案(Error Scenarios)

HTTP是围绕请求 - 响应消息传递模式设计的,这意味着它对错误方案有广泛的支持。HTTP的设计允许用错误描述来响应用请求、资源。或者提供细微的状态信息以区分成功场景,WebSocket协议仅支持连接建立错误的场景。建立连接并交换消息后,必须在消息传递层中设计解决文案以应对错误情况。

同步事件(Synchronized Events)

请求 - 响应模式非常适合需要同步或必须以序列化方式进行的操作。HTTP响应代表一个明确的请求,允许对其进行后续操作。在WebSockets中,此细节留给了消息传递层,WebSocket协议不保证以任何形式确认消息。

但是,在设计中应该尽量避免假设客户端始终能完美地同步他们的操作。尽可能的提供无状态交互模式,或者允许客户端并行地发出请求,因为这将使应用程序可以更好的应对不可避免的网络问题,或有bug的客户端行为。

WebSocket的应用场景

就像HTTP一样,WebSocket也有一组自己的应用场景,也是一些项目的最佳选择,请记住在文章开头时的注意事项,因为以下指南没有考虑任何特殊的消息传递协议。

快速响应时间(Fast Reaction Time)

当客户端需要对更改做出快速反应时(尤其是无法预测的更改),WebSocket可能是最佳的选择。考虑允许多个用户实时聊天的聊天应用程序,如果使用WebSockets,则每个用户都可以实时发送和接收消息。与REST相比,WebSockets更高效,因为它们不需要为发送和接收的每条消息创建有额外开销的HTTP请求/响应。

持续的更新(Ongoing Updates)

当客户端关心资源状态的持续更新时,WebSockets通常是一个不错的选择,当客户端无法预测何时会发生变化或短期内可能发生变化时,WebSockets会特别适合。

另外,如果客户端能够预测更改发生的时间或不频繁发生的更改,HTTP可能更合适——例如,每小时更改一次的资源,或者只在知道修改了相关资源之后才更改。

如果客户端不知道相关的资源被修改了(例如,因为其他客户端修改了它,或者服务修改了它),那么选择WebSockets会更好。

Ad-hoc消息传递(Ad-hoc Messaging)

WebSocket协议不是围绕请求 - 响应而设计的。消息可以在任何时候从连接的任一端发送,并且对于一个消息没有本地支持来表示它与另一个消息相关。这使得该协议非常适合“发送就忘记”的消息传递方案,并且非常适合于事务性要求。如果应用程序需要,消息传递层必须满足事务需求。

具有小负载的高频消息传递(High-Frequency Messaging with Small Payloads)

WebSocket协议提供了交换消息的持久连接。这意味着单个消息不会因为需要建立传输而产生额外的开销,诸如建立SSL、内容协商和交换大容量头等仅在建立连接时产生开销,而每条消息并不需要额外开销。

另一方面,虽然HTTP v1.1可能允许多个请求重用单个连接,但通常会有少量超时时间用于控制资源消耗。由于WebSockets专为长期连接方案而设计,因此可以避免建立连接和发送HTTP请求/响应头的开销,从而显著提升性能。

但是,这不应该被极端的使用。如果只发送少量消息或者消息传递非常少,应避免使用WebSockets。除非客户必须快速接收或进行更新,否则维护开放的连接可能是不必要的资源浪费。

错误的使用HTTP的场景

依赖于客户端轮询服务,而不是由用户主动发起。

需要频繁的服务调用来发送小消息。

客户端需要快速响应对资源的更改,并且无法预测更改何时发生。

由此产生的设计成本过高,扪心自问:WebSocket解决方案在设计、实现、测试和操作上是否大大减少了工作量?

错误的使用WebSockets的场景

该连接仅用于极少数事件或非常短的时间,客户端无需快速响应事件。

需要一次打开多个WebSockets到同一服务。

打开WebSocket,发送消息,然后关闭它 - 然后再重复该过程。

消息传递层中重新实现请求/响应模式。

由此产生的设计成本过高,问问自己:HTTP解决方案在设计,实施,测试和运营方面的工作量大大减少了吗?

结论

建议假设API默认为传统HTTP,除非上述的指导原则可以说服使用WebSockets。