Sag*_*gar 11 virtual-machines linux-networking socket
我们有几个最近转换成虚拟机的生产系统。我们的一个应用程序经常访问 MySQL 数据库,并且为每个查询创建一个连接、查询并断开该连接。
这不是查询的合适方式(我知道),但我们有一些我们似乎无法绕过的限制。无论如何,问题是:虽然机器是物理主机,但程序运行良好。转换为虚拟机后,我们注意到与数据库的间歇性连接问题。有一次,TIME_WAIT 中有 24000 多个套接字连接(在物理主机上,我看到的最多是 17000 - 不好,但不会引起问题)。
我希望重用这些连接,以便我们看不到连接问题,因此:
问题:
将 tcp_tw_reuse 的值设置为 1 可以吗?有哪些明显的危险?有什么理由我永远不应该这样做吗?
另外,有没有其他方法可以让系统(RHEL/CentOS)防止如此多的连接进入 TIME_WAIT,或者让它们被重用?
最后,更改 tcp_tw_recycle 会做什么,这对我有帮助吗?
提前,谢谢!
您可以安全地减少停机时间,但您可能会遇到因网络上的连接不正确关闭而导致数据包丢失或抖动的问题。我不会从 1 秒开始调整,从 15-30 开始,然后按照自己的方式进行调整。
此外,您确实需要修复您的应用程序。
RFC 1185在 3.2 节中有很好的解释:
当 TCP 连接关闭时,TIME-WAIT 状态下的 2*MSL 延迟会占用套接字对 4 分钟(参见 [Postel81] 的第 3.5 节。建立在 TCP 上的应用程序关闭一个连接并打开一个新连接(例如,使用 Stream 模式的 FTP 数据传输连接)每次必须选择一个新的套接字对。这个延迟有两个不同的目的:
Run Code Online (Sandbox Code Playgroud)(a) Implement the full-duplex reliable close handshake of TCP. The proper time to delay the final close step is not really related to the MSL; it depends instead upon the RTO for the FIN segments and therefore upon the RTT of the path.* Although there is no formal upper-bound on RTT, common network engineering practice makes an RTT greater than 1 minute very unlikely. Thus, the 4 minute delay in TIME-WAIT state works satisfactorily to provide a reliable full-duplex TCP close. Note again that this is independent of MSL enforcement and network speed. The TIME-WAIT state could cause an indirect performance problem if an application needed to repeatedly close one connection and open another at a very high frequency, since the number of available TCP ports on a host is less than 2**16. However, high network speeds are not the major contributor to this problem; the RTT is the limiting factor in how quickly connections can be opened and closed. Therefore, this problem will no worse at high transfer speeds. (b) Allow old duplicate segements to expire. Suppose that a host keeps a cache of the last timestamp received from each remote host. This can be used to reject old duplicate segments from earlier incarnations of the
*注意:发送 FIN 的一方可能知道它需要什么程度的可靠性,因此它应该能够确定 FIN 接收方的 TIME-WAIT 延迟长度。这可以通过 FIN 段中的适当 TCP 选项来实现。
Run Code Online (Sandbox Code Playgroud)connection, if the timestamp clock can be guaranteed to have ticked at least once since the old conennection was open. This requires that the TIME-WAIT delay plus the RTT together must be at least one tick of the sender's timestamp clock. Note that this is a variant on the mechanism proposed by Garlick, Rom, and Postel (see the appendix), which required each host to maintain connection records containing the highest sequence numbers on every connection. Using timestamps instead, it is only necessary to keep one quantity per remote host, regardless of the number of simultaneous connections to that host.
我认为将此值更改为 1 没问题。更合适的方法可能是使用以下命令:
[root@server]# sysctl -w net.ipv4.tcp_tw_reuse=1
Run Code Online (Sandbox Code Playgroud)
据我所知,没有明显的危险,但快速的谷歌搜索产生了这个链接,它确认这tcp_tw_reuse
是比 更好的选择tcp_tw_recycle
,但无论如何都应该谨慎使用。
小智 6
这并没有回答您的问题(并且已经晚了 18 个月),但建议了另一种使您的旧应用程序重用端口的方法:
在系统上设置tcp_tw_reuse
(或tcp_tw_recycle
)的一个有用的替代方法是将共享库(使用LD_PRELOAD
)插入到您的应用程序中;然后该库可以允许重用端口。这使您的旧应用程序允许端口重用,而无需在系统上的所有应用程序上强制执行此操作(无需修改您的应用程序),从而限制您调整的影响。例如,
LD_PRELOAD=/opt/local/lib/libreuse.so ./legacy_app
Run Code Online (Sandbox Code Playgroud)
这个共享库应该拦截socket()
调用,调用真正的 socket(),并在返回的套接字上设置 SO_REUSEADDR 和/或 SO_REUSEPORT。有关如何执行此操作的示例,请查看http://libkeepalive.sourceforge.net(这会打开 keepalive,但打开 SO_REUSEPORT 非常相似)。如果您行为不端的旧版应用程序使用 IPv6,请记住将第 55 行libkeepalive.c
从
if((domain == PF_INET) && (type == SOCK_STREAM)) {
Run Code Online (Sandbox Code Playgroud)
到
if(((domain == PF_INET) || (domain == PF_INET6)) && (type == SOCK_STREAM)) {
Run Code Online (Sandbox Code Playgroud)
如果你被卡住了,给我发电子邮件,我会写代码并发送给你。