最近,我花了相当多的时间来查找生产中的问题,其中poll()
连接的客户端的数据库服务器消失将导致最多2个小时的挂起(长时间等待libpq客户端库中的调用)。深入研究问题,我意识到应该调低这些内核参数,以便及时发现断开的TCP连接:
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_retries2 = 15
上面的四个值来自Ubuntu 12.04计算机,看起来这些默认值与当前的Linux内核默认值保持不变。
这些设置似乎严重偏向于保持现有连接的打开状态,并且对于keepalive探针极为ing。AIUI,默认tcp_keepalive_time
值为2小时,这意味着当我们等待远程主机的响应时,我们将耐心等待2小时,然后再发起一次keepalive探测以验证我们的连接仍然有效。然后,如果远程主机不响应keepalive探测,则我们将对这些keepalive探测重试9次(tcp_keepalive_probes
),相隔75秒(tcp_keepalive_intvl
),因此,在我们确定连接真正失效之前,还需要再花11分钟。
这与我在该字段中看到的内容相符:例如,如果我启动一个psql
连接到远程PostgreSQL实例的会话,并且有一些查询等待响应,例如
SELECT pg_sleep(30);
然后使远程服务器严重死亡(例如,丢弃该机器的流量),我发现我的psql会话等待长达2个小时11分钟才能发现连接已死。您可能会想到,这些默认设置会对我们在数据库故障转移事件期间与数据库交谈的代码造成严重问题。调低这些旋钮很有帮助!而且我发现我并不孤单地建议调整这些默认值。
所以我的问题是:
- 这样的默认设置多长时间了?
- 使这些TCP设置成为默认设置的最初理由是什么?
- 有任何Linux发行版会更改这些默认值吗?
对于这些设置的任何其他历史或观点,将不胜感激。
TCP_KEEPIDLE
,TCP_KEEPCNT
和TCP_KEEPINTVL
。
TCP_USER_TIMEOUT
,而不是在net.ipv4.tcp_retries2
系统范围内进行设置。当然,许多应用程序(例如我的示例中的PostgreSQL)尚不支持TCP_USER_TIMEOUT
。