关于javascript:压测场景下的-TIMEWAIT-处理

5次阅读

共计 4687 个字符,预计需要花费 12 分钟才能阅读完成。

简介:压测场景下的 TIME_WAIT 解决

=====

某专有云我的项目具备压测场景,在 Windows 的压测机上用 LoadRunner 进行业务的压力测试,压测运行一段时间后呈现大量端口无奈调配的报错。
其实通过问题形容,以及 Windows 的报错信息根本确定是压测机的问题。但可能起因较多,始终未能达成统一。所以,趁机剖析了客户端的压测机成为压测瓶颈的可能,除了 CPU、网络、I/O 等机器性能参数外,仍需思考网络协议引入的资源短缺问题。
注:以下内容的目标是理清 TCP 协定中比拟含糊的内容,对协定比拟相熟的能够疏忽。

  1. TIME_WAIT 根底:RFC 793 TCP 协定

==============================

家喻户晓,TCP 存在三次握手,四次挥手过程。其具体设计的目标,简而言之,是为了在不稳固的物理网络环境中确保牢靠的数据传输;因而,TCP 在具体实现中退出了很多异样情况的解决,整体协定就变得比较复杂。
要了解 TCP 协定,举荐浏览 RFC 793,可参考文后链接理解详情[1]。同时,也要了解“TCP state transition”状态机,如下图所示,可参考文后材料理解详情[2]。

图 1. TCP 状态转换图

本文仅针对 TW 在 TCP 协定中的作用进行探讨,不波及整体协定的剖析。四次挥手后的 TIME_WAIT 状态,后续将以 TW 缩写代替。

2.1 TW 作用

首先,次要作用是保障 TCP 连贯敞开的可靠性。
思考下在四次挥手过程中,如果被动敞开方发送的 LAST_ACK 失落,那么被动敞开方会重传 FIN。此时,如果被动敞开方对应的 TCP Endpoint 没有进入 TW 状态而是间接在内核中清理了,依据协定,被动敞开方会认为本人没有关上过这个端口,而以 RST 响应被动敞开方重传的 FIN。最终该行为导致被动敞开方认为连贯异样敞开,在业务上可能会收到异样报错等状况。
其次,TW 状态同时也能防止雷同的 TCP 端口收到在网络上前一个连贯的反复数据包。
实践上,数据包在网络上过期工夫对应即 MSL(Maximal Segment Lifetime),随着操作系统的一直倒退,也有例外情况,这部分搜寻 PAWS 应该能够看到不少相似的文章阐明。
再次,端口进入 TW 状态 同时也防止了被操作系统疾速重复使用的可能。

2.2 TW 造成的起因

当一台主机操作系统被动敞开 TCP Endpoint(socket)时,该 TCP Endpoint 进入 TW 状态。以 Windows 为例,Windows 内核会对 TCP Endpoint 数据结构进行相应清理,而后放入额定的 TW queue 中,设置 2MSL 的定时器,期待定时器超时后调用对应的开释代码。Linux 上的实现也是相似。
目前较多的说法是 ”TCP 连贯 ” 进入 TW,但咱们可能须要了解 “ 连贯 ” 其实是形象的概念。实际上 ” 连贯 ” 在逻辑上存在,因为客户端和服务器端以及两头可能波及的 4 层设施同时为一次传输创立了关联的 TCP 资源(Endpoint,或者 Session)。精确了解 TW 状态,即 TCP EndpointTW 进入 TW 状态。

2.3 小结

TW 是为了保障 TCP 连贯失常终止(防止端口被疾速复用),也是为了保障网络中迷失的数据包失常过期(避免前一个连贯的数据包被谬误的接管)。
TW 暗杀术,可参考文后材料理解详情[3]。

  1. 概念廓清

========

欢送探讨
几个可能比拟含糊的中央,明确如下:

  1. 作为连贯单方,客户端和服务器端的 TCP Endpoint 都可能进入 TW 状态(极其状况下,可能单方同时进入 TW 状态)。

该状况在逻辑上是成立的,可参考文后材料理解详情[4]。

  1. TW 是规范的一部分,不代表 TCP 端口或者连贯状态异样。(这个概念很重要,防止陷入某些不必要的陷阱。)
  2. CLOSE_WAIT 只管也是规范的一部分,但它的呈现预示着本端的 TCP Endpoint 处于半敞开状态,起因经常是应用程序没有调用 socket 相干的 close 或者 shutdown。可能的起因是应用程序仍有未发送实现的数据,该状况下 CLOSE_WAIT 最终还是会隐没的。具体形容这部分,长期有 CLOSE_WAIT 状态的端口迟缓累积,这种状况是须要引起留神的,累积到肯定水平,端口资源就不够了。

针对后面的 TCP Endpoint 这个词语,可能很多人不太理解,这边也简略阐明下:
在 Windows 2008 R2 之前,socket 是用户态(user mode)的概念,大多数 Windows socket 应用程序根本都基于 Winsock 开发,由中间层 AFD.sys 驱动翻译成内核 tcpip.sys 协定栈驱动 所能承受的 TCP Endpoint 数据结构。在 2008 R2 之后,微软为了不便内核的网络编程,在 Windows Kernel 中提供 WSK,即 Winsock 在内核的实现。文中提到的 TCP Endpoint 是在 Windows 内核中由 TCPIP.sys 驱动文件实现的 TCP 数据结构,也对应 Linux 上的 socket。该文简略以 Endpoint 代指内核的 ”socket”。

  1. TW 优化伎俩

===========

对于 Linux,优化伎俩曾经进行了很多探讨了,以 Centos 为例,

  1. 在 timestamps 启用的状况下,配置 tcp_tw_reuse 和 tcp_tw_recycle。

针对客户端,连贯申请发起方。
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1

针对服务器端,连贯申请接管方
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1
注:tcp_tw_recycle 的启用会带来一些 side effect,具体在 NAT 地址转换场景下,容易产生连贯异样问题。
可参考文后材料理解详情[4]。

  1. 配置 max_tw_buckets,连贯申请发起方接管方通用,但须要留神这个选项自身有违 TW 设计的初衷。

net.ipv4.tcp_max_tw_buckets = 5000

  1. 配置 ip_local_port_range,连贯申请发起方。

net.ipv4.ip_local_port_range = 5000 65535

针对 Windows,材料较少,这边借之前的工作教训,总结如下:

  1. Windows Vista / Windows Server 2008 之前的操作系统,注册表

端口范畴:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters
MaxUserPort = 0n65534
TW 超时工夫:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters
TcpTimedWaitDelay = 0n30

  1. Windows 7 / Windows Server 2008 R2 及其之后的版本

端口范畴:
netsh int ipv4 set dynamicport tcp start=1025 num=64511
TW 超时工夫:
HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesTcpipParameters
TcpTimedWaitDelay = 0n30

Windows Server 2012 and earlier: 30-300 (decimal)
Windows 8 and earlier: 30-300 (decimal)
Windows Server 2012 R2 and later: 2-300 (decimal)
Windows 8.1 and later: 2-300 (decimal)
注:

  • 任何波及注册表的批改,只有重启机器才会失效。
  • 与 Linux 不同,Windows 没有疾速回收机制,不存在疾速回收 TW 的可能,只能期待 2MSL 过期(即 TcpTimedWaitDelay)。
  • Windows 惟一能疾速回收 TW 状态的 Endpoint 的状况:

新连贯申请的 SEQ 序列号 >TW 状态的 Endpoint 记录的 SEQ 序列号。
此时,内核会认为该 SYN 申请非法。这里,这个 TW 状态的 TCP Endpoint 肯定是在服务端(通过 socket accept 关上的 服务端口)。(为了这个能力,Windows 的 RFC 1323 选项必须关上,内容能够自行搜寻。)

  1. 压测客户端无奈调配端口的起因剖析

====================

端口无奈调配有两种可能:

  • 齐全随机的动静端口申请,报错端口调配异样,根本是操作系统没有可用端口。
  • 指定端口的绑定申请报错端口调配异样,可能存在端口应用抵触问题。

针对第一种状况,首先须要通过 netstat -ano 进行疾速查看,剖析是否存在端口占满的状况,以及占满端口的 TCP Endpoint 状态。针对不同的状态,思考不同的计划。
比方,极其状况下,没有任何异样的服务器上,端口调配失败问题,可参考文后材料理解详情 [5]。
以 Windows 操作系统 TW 状态 Endpoint 占满可用端口场景为例(在 Linux 上产生的可能性较低),剖析问题前须要大略理解 Windows 上端口调配原理。

  • Windows 和 Linux 在动态分配端口的机制上有很大的不同。
  • Linux 以浅显的了解应该是针对五元组的调配,即可能存在雷同的动静端口拜访不同服务器的服务端口。
  • Windows 的动静端口调配实现基于 Bitmap 查找,无论拜访哪里,动静端口的池子最大为 1025 – 65536,即 64511 个。
  • 思考到最短 30 秒的 TW 超时工夫,如果依照 64511/29 = 2225 ports/s 的速度去创立端口,那么很可能在 30 秒后继续产生端口无奈调配的问题。
  • 这还是在连贯解决比拟疾速的状况下,如果连贯建设后不敞开,或者敞开工夫比拟久,创立端口的速度仍需继续降落来躲避端口问题。

了解了 TW 的造成起因,相应的解决方案也就比较清楚了。

  1. 升高应用程序创立端口的速度。思考连贯持续时间和 TW 超时工夫,计算绝对正当的连贯建设速度。不过,物理机操作系统、CPU/ 内存、网络 IO 等均可能影响连贯状态,准确计算很难;同时,就应用程序而言,升高端口创立速度须要额定的逻辑,可能性不大。
  2. 在这个压测场景下,通过减少机器的形式来变相缩小端口的需要。压测个别思考某个固定阈值下整体零碎的响应状况。在压力固定的状况下,能够通过扩散压力的形式来缩小端口资源的占用。
  3. 扭转连贯的行为,应用长久连贯(注:非 HTTP 的长连贯),例如针对 500 个并发,仅建设 500 个连贯。益处不言而喻,但害处也很显著,长久连贯不大合乎用户实在行为,压测后果可能失真。同时,该办法须要应用程序上的反对。
  4. 不让机器的 TCP Endpoint 进入 TW 状态,可参考以下 2 种计划。
    a) 不让该机器被动敞开连贯,而让对方被动敞开。这样,该主机进入被动敞开过程,在利用敞开 TCP Endpoint 之后,可间接开释端口资源。一些协定自身就有管制是否放弃连贯或者申请对方敞开连贯的行为或者参数,在思考这类问题的时候,能够适当进行利用。比方 HTTP 的长短连贯,可参考文后材料理解详情[4]。b) 通过 TCP Reset 强制开释端口。TCP Reset 能够由任何一方收回,无论是发送方还是接管方,在看到 TCP Reset 之后会立即将对应 TCP Endpoint 拆除。

这里,可设置 socket 的 SO_LINGER 选项,比方配置 Nginx,可参考文后官网文档理解详情[6]。

图 2:Nginx Lingering 配置参考阐明

针对压测工具自身,官方网站上也有相似 ABRUPT 选项,可参考文后官网文档理解详情[7]。

图 3:LoadRunner ABRUPT 配置选项阐明

作者:陈鸽
原文链接
本文为阿里云原创内容,未经容许不得转载

正文完
 0