TCP连接队列捕获现象Stratus 上监听端口X的服务器应用程序无法成功建立与任何试图连接该端口的客户端的连接。即使是同一客户端连接其他端口也能正常工作。典型解决方案是关闭并重启服务器应用程序。本文将阐述队列捕获现象的成因,并提供其他更温和的解决方案。
TCP后备队列是待处理连接的队列,即已接收但尚未被接受的连接请求。在基于OpenVOS 17.1之前的版本编译的应用程序中,以及在OpenVOS 17.1上编译但未包含POSIX库的应用程序中,连接请求在被应用程序接受前不会收到确认。客户端将在3至10次之间以递增间隔重发连接请求数据包。 具体细节取决于客户端操作系统及其配置方式。当服务器应用最终接受连接请求时,STCP协议栈将发送确认响应。只要该确认响应在客户端放弃重传前被接收,连接即告建立,通信即可开始。
积压捕获场景需要满足若干条件
- 服务器与客户端之间(但非客户端与服务器之间)存在临时网络故障。这使得客户端的连接请求能够被服务器接收,但阻止了服务器的连接确认被客户端接收。
或
服务器应用程序因某些原因延迟调用accept函数。
- 客户端持续发送连接请求;当当前请求超时后,客户端会发送新的请求。客户端的超时值必须小于服务器的超时值。
- 客户端与服务器之间某处的状态防火墙或其他设备会超时处理客户端的连接请求,并丢弃服务器的连接确认响应而不向服务器发送回响应。该超时值必须小于服务器的超时值。
遗憾的是,这种条件组合并非乍看之下那么不可能。
通常始于网络中断,导致服务器发出的数据包无法到达客户端,但客户端发出的数据包仍能到达服务器。当客户端的连接请求数据包到达服务器时,会被放入后置队列。当服务器应用程序调用accept代码时,该代码会从后置队列中提取连接请求并发送连接确认。 由于网络中断导致服务器未收到数据包确认,它会重传连接确认。客户端的TCP协议栈同样因未获确认而重传连接请求。 一段时间后,客户端TCP栈放弃等待,客户端应用程序发送新请求。此时服务器仍在响应首次请求。约1.5分钟后(默认值),服务器超时并从后备队列提取下一个请求。 此时客户端已重发第二次请求,甚至可能正在处理第三次请求。这些请求同样滞留在后备队列中。其他客户端的连接请求虽可能进入后备队列,但要成功建立连接,其超时时间必须大于服务器超时时间乘以该请求在队列中的排队时间。 当网络故障修复后,状态防火墙会因静默丢弃连接确认而延续故障——由于其状态保存时长短于服务器超时时间,导致这些确认已无对应状态可供处理。
你怎么认出这个的?
首先,积压队列已满或至少正在填满。您可以使用此命令显示连接的积压队列。
analyze_system -request_line (字符串匹配队列 -或 syncnt (字节 3Bx) dump_st +
cbq -full -lport 7654 -faddr 0x) -quit
OpenVOS 版本 17.0.2au,analyze_system 版本 17.0.2au
当前进程为 154,ptp 91CC7100,Noah_Davids.CAC
同步计数器 6
后备队列 5
就绪时间 11:41:19
|
本地端口值(lport)即本地端口号,此处为7654。外地址(faddr)值设为0时,输出仅限于监听套接字。若后备队列值加1等于同步计数值(syncnt),则表示后备队列已满。当同步计数值大于0且持续上升时,表明后备队列正在填充。后备队列的大小由应用程序在调用监听函数时设定。
其次,您需要查看网络协议跟踪记录。该记录将显示:最后一次连接请求未获得应答,而先前连接请求的连接确认信息虽已发送,却未收到任何形式的响应。
图1中的跟踪记录展示了这一过程。每条连接都标有流索引并采用颜色编码。客户端首次连接请求出现在时间点0的帧1中。确认帧在帧2发送,随后在帧3中重传。帧4是客户端重传的连接请求。由于STCP已发送连接确认,帧4仅触发了帧5中的TCP确认。 帧6和7是重传的连接确认。帧8是客户端重传的连接请求。帧9是重传连接请求触发的TCP确认,帧10则是另一份重传的连接确认。帧11是客户端发起的另一份连接请求,但针对新的第二个连接。需注意此请求未获响应,帧12显示了重传的连接请求。 第13帧显示连接确认,但仍属于首次连接。第14帧是第二次连接请求的重传。第15帧显示客户端发起的第三次新连接请求,第16和17帧为重传。第18帧是首次连接确认的再次重传。 帧19是又一次连接请求,帧20和21为重传,帧22则是第四个新连接请求。最终在帧23中,STCP放弃了首次连接请求并发送重置信号,随后在帧24对第二次连接请求发送确认,帧25为重传。至此,相信您已理解其工作原理。
STCP从帧0到帧23耗时超时,总计106.9秒。 尽管客户端在超时后不会发送重置请求,但第二次与第三次连接请求(第11帧至第15帧)间隔为29.152秒,第三次与第四次(第15帧与第19帧)间隔为25.8秒,远快于STCP协议。
你该怎么做才能避免这种情况?
最佳解决方案是升级至OpenVOS 17.1并使用POSIX库重新编译应用程序。此操作将彻底避免该问题,因为STCP会立即发送连接确认,无需等待应用程序调用accept函数。但此举可能改变应用程序的其他行为,因此需对应用程序进行仔细测试。若无法升级和重新编译,您可
- 重新配置正在丢弃连接确认的状态化网络设备,使其改为响应重置。当STCP接收到重置时,将转而处理后备队列中的下一个连接请求。结果是,被状态化设备超时的连接请求将迅速从队列中清空。后续的任何连接确认都将由客户端处理,客户端要么发送自己的重置,要么确认这些请求。
- 阻止客户端发送连接请求,直至服务器后备队列清空。
- 关闭服务器应用程序的监听套接字并重新打开它。通常,应用程序并未设计此操作,因此您需要停止并重新启动服务器应用程序。
- 将syn_rcvd_abort值配置为小于客户端超时值的数值。该值需通过analyze_system请求中的set_stcp_param指令进行修改。
analyze_system -request_line 'set_stcp_param syn_rcvd_abort 15' -quit OpenVOS 版本 17.0.2au,analyze_system 版本 17.0.2au 当前进程为 151,ptip 91530AC0,Noah_Davids.CAC 将 tcp SYN_RCVD 超时 (syn_rcvd_abort) 从关闭改为 15 准备就绪 11:07:44在上例中,超时设置为15秒。有效值范围为1至180,值为0表示使用默认值(约100秒)。
这将防止单个客户端在积压队列中造成大量积压。该值应设置多短取决于同时访问服务器的客户端数量。此方法的问题在于它会影响所有客户端和所有服务器端口,无法为不同端口组分别设置不同值。此外,值过低可能导致某些通过高延迟链路建立的连接失败,而若计时器更长则这些连接本可成功。 选择最优值更多是门艺术而非科学。
