我在一个AWS实例上运行一台服务器(使用龙卷风python),我遇到了websocket延迟的峰值。
分析从将websocket消息发送到客户端(客户端随后立即将ack消息发送回服务器)到服务器接收到ack消息的往返时间,得到平均<。1秒,但我注意到有时会达到3秒。注意:在本地运行服务器时不会出现峰值。
造成这种情况的原因或解决方法是什么?我查看了CPU的使用情况,它最多只上升了40%。峰值与繁忙的流量无关(通常是2到3个客户端),客户端的互联网似乎也很好。我发现很难相信这个实例在如此低的使用率下超出了容量。
峰值为3秒这一事实实际上告诉了你更多关于问题性质的信息,而不是你可能怀疑的。
这是数据包丢失。
众所周知,TCP可以提供"可靠"的传输,保证远端按照发送的顺序接收发送的有效载荷,因为TCP在发送有效载荷之前会按照正确的顺序重新组装。实现这一点的一个重要方式是通过自动重传被认为已经丢失的分组。
您永远猜不到重传丢失数据包的默认初始计时器值。或者,也许,现在,你会的。
在许多(如果不是大多数的话)实现中,这是3秒,基于几年前建立的标准,当时当今传输链路的带宽和延迟是闻所未闻的,也许是无法想象的。
你不会在websocket服务器或客户端软件上看到重传的证据,因为TCP保护更高层不知道它发生了。。。但3秒钟完全暴露了这正是问题所在。
如果你用数据包嗅探器观察网络流量,你会看到流量的重新传输,尽管这只能用来确认这是问题所在。
它可能是从服务器到客户端的丢失,也可能是从客户端到服务器的丢失。后者通常更有可能,因为客户端通常具有较低的可用上行带宽。。。但是分组丢失的方向性并不能清楚地指示其发生的物理位置。除非您的客户端跟踪本地时间,以便将请求和响应启动时间关联起来,否则您不知道延迟是在消息中还是在确认中。
在相对较轻的负载下,问题似乎不太可能出现在您的实例或您一侧的AWS网络中,而且您显然无法将嗅探器连接到互联网上的任意点来确定问题。
考虑到这样的情况,证明问题不在的哪里,而不是 在其中一种技术是通过位于其他地方的不同设备,如不同的AWS地区或另一家云提供商,为流量创建一条故意绕行的道路。 当然,首先,您需要学习使用wireshark来发现这些重传。 然后,使用简单的TCP连接代理(如HAProxy),甚至是 这样的配置将侦听来自客户端的连接,当建立连接时,将创建一个到目的地(您的websocket服务器)的新TCP连接,但重要的是,它们只在有效负载级别将两个连接连接在一起,而不是在TCP级别,当然也不会更低——所以重传只能在这个中间服务器和有数据包丢失问题的连接结束之间的线路上看到。另一端不会显示任何重新传输的证据,只是数据到达的时间比预期的要晚。 为了使此测试有意义,代理需要位于远离服务器和客户端的位置,并且没有有意义的公共基础设施——因此建议将其放置在不同的AWS区域。同一地区的不同可用性区域可能在某种程度上共享共同的互联网基础设施,因此这还不够远。 如果 相反(我建议,更有可能),如果代理和服务器之间的路径没有重新传输,但客户端和代理之间的路径仍然是脏的,那么就消除了服务器及其基础设施作为问题根源的问题。如何进行取决于你,但在这一点上你确实知道问题是什么。。。不是。 另外两种可能性: 双方都保持肮脏,这是最不可能发生的情况。故障排除的规则1是最初假设您只有一个问题,而不是两个问题。 或者,当流量使用这种设置时,双方都突然出乎意料地干净了,这表明你的测试设置是围绕着一块断开的互联网路由的。你已经"解决"了,但不知道如何解决。我们也希望这不是结果,但考虑到全球互联网的变幻莫测,您的堆栈可能包括这样的组件,并基于地理位置DNS选择中间端点,这并非不可想象。这看起来像是一个卷积,但确实有它的位置。 这种策略实际上是S3转移加速功能背后逻辑的一部分。内容并不离最终用户更近,但来自浏览器的TCP连接正在AWS边缘网络中的设备上终止,位置通常离浏览器更近,并建立了返回存储桶的第二个TCP连接,有效载荷连接在一起。。。是的,它更快、更稳定,随着距离和连接质量的变化,变化的意义变得更加显著。redir
或socat
等简单工具,在不同的位置配置代理服务器。client <--> proxy <--> server
在代理和服务器之间的路径上显示TCP重传,而不是在客户端和代理之间,那么问题很可能出在服务器、硬件、网络或Internet连接上,您必须相应地进行处理。