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