对于交互式Web应用程序,Websockets之类的东西越来越受欢迎。然而,由于客户端和代理世界并不总是完全兼容,人们通常使用一个复杂的框架,如“Socket. IO”,隐藏了几个不同的机制,任何情况下都可能禁用其他机制。
我只是想知道一个正确实现的长轮询的缺点是什么,因为今天的服务器像node.js这样很容易实现,并且依赖于旧的http技术,而http技术得到了很好的支持(尽管长轮询行为本身可能会破坏它)。
从高层次的Angular 来看,长轮询(尽管有一些额外的开销,对于中等流量的应用程序是可行的)类似于WebSockets所做的真正的推送行为,因为服务器实际上在他喜欢的时候发送它的答案(尽管有一些超时/心跳机制)。
因此,我猜由于更多的TCP/IP确认,我们有一些更多的开销,但没有像频繁轮询这样的恒定流量。
使用事件驱动服务器,我们将没有线程开销来保持连接阻塞。
那么,有没有其他的不利因素迫使像聊天这样的中等流量应用程序使用WebSockets而不是长时间轮询?
2条答案
按热度按时间6ju8rftf1#
开销
它每次都会创建一个新的连接,所以它会发送HTTP头...包括可能很大的cookie头。
此外,仅仅“检查是否有新的东西”是另一种毫无意义的连接。连接意味着许多项目的工作,如防火墙,负载平衡器,网络服务器...等。可能,建立连接是最耗时的事情,一旦您的IT基础设施有几个检查员。
如果您使用HTTPS,您将一次又一次地执行开销最大的操作,即TLS握手。一旦连接建立并且对称加密正常工作,TLS性能就很好,但是建立连接、密钥交换等过程并不快。
此外,连接完成后,日志条目会写入某个位置,计数器会在某个位置递增,内存会被消耗,对象会被创建......等等。例如,我们在生产和开发中使用不同日志记录配置的原因是,写入日志条目也会影响性能。
存在
长轮询用户何时连接或断开连接?如果您在给定的时刻检查此情况......您应该等待多长时间才能再次检查,以确保其断开连接或连接?
如果您的应用程序只是广播内容,这可能完全无关紧要,但如果您的应用程序是一个游戏,这可能非常相关。
不持久
这才是大事。
由于每次都创建一个新连接,如果您有负载平衡的服务器,在一个轮转场景中,您无法知道下一个连接将落在哪个服务器上。
当用户的服务器已知时,比如使用WebSocket时,您可以直接将事件推送到该服务器,服务器会将其中继到连接。如果用户断开连接,服务器可以直接通知用户不再连接,当再次连接时可以再次订阅。
如果用户在事件发生时连接到的服务器未知,则必须等待用户连接,然后您可以说“嘿,用户123在这里,给予我这个时间戳以来的所有新闻”,这会使它更麻烦一点。长轮询并不是真正的推送技术,而是请求-响应,因此如果您计划使用EDA架构,在某个点上,您将具有必须解决的某个级别的阻抗,例如,您需要一个事件聚合器,它可以从给定的时间戳(用户最后一次连接以请求新闻的时间)向您提供所有事件。
例如,SignalR(我猜它在.NET中相当于socket.io)有一个名为backplane的消息总线,它将所有消息中继到所有服务器,作为横向扩展的关键。因此,当用户连接到其他服务器时,“他的”挂起事件也在那里(!)这是一个“不太坏的方法”,但正如您所猜,会影响吞吐量:
局限性
使用背板时,最大消息吞吐量低于客户端直接与单个服务器节点通信时的最大消息吞吐量。这是因为背板将每条消息转发到每个节点,因此背板可能成为瓶颈。这种限制是否存在取决于应用程序。例如,以下是一些典型的SignalR场景:
*客户端到客户端(例如聊天):在这种情况下,如果消息数量随着客户机数量的增加而增加,则背板可能成为瓶颈;即消息速率是否随着更多客户端的加入而成比例地增长。
*高频实时(例如,实时游戏):不建议在此情况下使用背板。
对于某些项目,这可能是一个showstopper。
有些应用程序只是广播一般数据,但其他应用程序具有连接语义,例如多人游戏,因此将正确的事件发送到正确的连接非常重要。
恕我直言
长轮询对于小项目来说是一个很好的解决方案,但对于需要高频率和/或非常分段的事件发送的高可伸缩性应用来说,它成为了一个很大的负担。
c0vxltue2#
我实现了一个支持长轮询的Node.js Express服务器。我犯的最大错误是没有清理请求,这导致了服务器的速度变慢。如果您的服务器不支持并发或线程,一个基本任务是为请求/响应设置适当的超时,以将它们从循环中释放出来,这必须由您自己完成。