在什么情况下,WebSockets比轮询不高效?

41

虽然我理解上述问题的答案在很大程度上取决于您应用程序的架构,但我主要对非常简单的场景感兴趣。

如果我的应用程序每5秒或每分钟ping一次以获取更改,那么维护打开的Web Sockets连接发送的数据何时会超过通过简单轮询浪费的量?

基本上,我想知道是否有一种方法可以量化使用像Meteor这样的框架所产生的低效率,如果一个应用程序不一定需要实时更新,而只需要定期检查。

请注意,我的重点在带宽利用方面,而不是数据库访问时间,因为像Meteor这样的框架具有高度优化的方法,只请求数据库的更新。

2个回答

57
WebSocket连接的关键在于您无需为应用程序更改而向应用程序发出ping请求。客户端只需连接一次,然后服务器就可以在可用时直接向客户端发送更改。客户端不必询问。服务器只需在数据可用时发送数据。
对于任何类型的服务器启动数据,使用WebSocket比http轮询更有效率。除了提供更及时的结果(结果立即传递,而不是在下一个轮询间隔之前由客户端发现)。
对于纯带宽使用情况,详细信息取决于确切情况。 http轮询请求必须设置TCP连接并确认该连接(如果是SSL连接,则需要更多数据),然后发送http请求,包括属于该主机的任何相关cookie以及包括相关标头和GET URL。然后,服务器必须发送响应。大部分时间内,轮询的所有开销都将是完全浪费的带宽,因为没有新内容报告。
WebSocket以简单的http请求开始,然后将协议升级为WebSocket协议。 WebSocket连接本身根本不需要发送任何数据,直到服务器有数据要发送给客户端,在这种情况下,服务器只需发送数据包。发送数据本身的开销也要少得多。没有cookie,没有标头等……只有数据。即使在WebSocket上使用一些保持活动,那么该数据量与HTTP请求的开销相比微不足道。
因此,您将节省多少带宽取决于具体情况的细节。如果需要50次轮询请求才能找到有用数据,则与WebSocket场景相比,这些http请求中的每一个都完全浪费。带宽差异可能很大。
您想要一个仅需要定期检查的应用程序。一旦您进行的定期检查没有检索到任何数据,那就是浪费的带宽。这就是WebSocket的整个概念。当没有数据要发送时,您不会消耗带宽(或几乎不消耗带宽)。

7
在维持一个开放的WebSocket连接中使用了多少带宽?我认为,如果没有进行端口转发,则至少需要定期从客户端向服务器发送数据包,以便在服务器想要向客户端推送任何内容时进行NAT遍历。 - Ecksters
4
@Eckster - NAT实现会因为TCP连接的不活跃而有所不同。webSockets有发送ping/pong数据包的选项。这些数据包非常小(以字节计量,看起来只有2个字节的实际数据加上TCP开销),因此这不太可能对总带宽使用造成很大影响。在有数千个webSocket连接到服务器,并且每个连接偶尔会发送ping/pong时,保持连接通畅可能会在处理能力上表现得更明显。 - jfriend00
4
但是服务器资源会怎样呢?每5秒钟处理一次请求难道不比为每个用户永久保持连接更好吗? - Enrique
5
@Enrique - 空闲 socket 并不占用很多服务器资源,真正占用的只有系统内存。现在的服务器经过适当的定制,可以配置为处理百万个同时连接的 socket。如果您在决定使用 webSockets 还是 http 轮询之间,您需要构建一个使用场景来确定有多少个并发客户端、可接受的轮询间隔以及客户端实际上有多频繁地接收新数据,然后您才能开始建模哪种方法更有效率。魔鬼藏在细节中。 - jfriend00
2
@Enrique - 在光谱的一端,如果客户端只需要每30分钟轮询一次,则使用http请求可能是正确的方式,但是如果客户端需要服务器端更改的低延迟(例如在几秒钟内),那么使用http轮询将比使用webSocket对服务器造成更大的负担。 http长轮询也是一种中间解决方案,但通常被webSockets取代。 - jfriend00
显示剩余3条评论

24

我认为 @jfriend00 已经非常清楚地回答了这个问题。不过,我想补充一些想法。

通过插入 Websockets 对比 HTTP 的最坏情况(虽然不太可能),你会清楚地看到 Websocket 连接在带宽方面(以及可能的整体性能方面)始终具有优势。

这是 Websockets v/s HTTP 的最坏情况:

  • 你的代码使用 Websocket 连接完全相同的方式来进行轮询请求。

    (我知道这不是你会做的事情,但这是最坏的情况)。

  • 每个轮询事件都得到了正面回答 - 意味着没有浪费任何 HTTP 请求。

这是 Websockets 的最坏情况,它们被设计用于推送数据而不是轮询...即使在这种情况下,Websockets 仍将节省您带宽和 CPU 循环。

说真的,即使忽略 DNS 查询(由客户端执行,因此您可能不关心它)和 TCP/IP 握手(对客户端和服务器都很昂贵),Websocket 连接仍然更具性能和成本效益。

我来解释一下

每个 HTTP 请求都包含大量数据,例如 cookie 和其他标头。在许多情况下,每个 HTTP 请求还需要进行客户端身份验证...很少有数据会被随意赠送。

这意味着 HTTP 连接需要通过所有这些数据(可能还进行客户端身份验证)每次请求[无状态]

然而,Websocket 连接是有状态的。数据只发送一次(而不是每次请求时都发送)。客户端身份验证仅在 Websocket 连接协商期间进行。

这意味着 Websocket 连接仅需要通过相同的数据(可能还进行客户端身份验证)每个连接一次(所有轮询只需要一次)。

因此,即使在这种最坏的情况下,轮询总是正面回答且 Websockets 用于轮询而不是推送数据,Websockets 仍将节省服务器的带宽和其他资源(即 CPU 时间)。

简单来说,我的答案是“永远不会”。Websockets 永远不会比轮询方式更低效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接