- Notifications
You must be signed in to change notification settings - Fork18.7k
Description
TCP keep-alives are enabled by setting theSO_KEEPALIVE socket option. When keep-alives are enabled, the operating system will probe idle connections and close connections with an unresponsive peer.
Linux,FreeBSD, andWindows permit configuring keep-alive probes with theTCP_KEEPIDLE,TCP_KEEPINTVL, andTCP_KEEPCNT socket options. (Darwin appears to callTCP_KEEPIDLETCP_KEEPALIVE.) These options set the idle duration before the first probe is sent, the interval between probes, and the maximum number of probes to send before declaring a connection dead, respectively.
Thenet package permits configuring TCP keepalive behavior with:
Setting the keep-alive period sets bothTCP_KEEPIDLE andTCP_KEEPINTVL. There is no way in thenet package to setTCP_KEEPCNT or otherwise configure how long it takes to declare a connection dead. There is no way to set different values for the idle period and the probe interval.
Since Go 1.12 (https://go.dev/cl/107196), thenet package has setTCP_KEEPIDLE andTCP_KEEPINTVL on all new sockets to 15 seconds by default.
This 15 second value is not appropriate for all uses. For example,#48622 complains that the default keep-alive settings cause excessive CPU consumption on mobile devices due to frequent probes. Reducing the time until the first keep-alive probe is sent withDialer.KeepAlive also reduces the time between probes; setting the period to five minutes will cause the kernel to take ~50 minutes to detect a dead connection.
I propose that we change thenet package functions which set the keep-alive period to setTCP_KEEPIDLE, but notTCP_KEEPINTVL. It is surprising and not useful for a "keep-alive period" of ten minutes to translate into a connection being declared dead only after several hours of unresponsiveness.
I propose that we also add a finer-grained API for configuring keep-alive behavior. I haven't exhaustively surveyed the operating systems we support, but Linux, Windows, Darwin, and at least one BSD all appear to support the same three settings. It's possible to set these viagolang.org/x/sys, but providing a common way to configure them in thenet package seems reasonable.
The following API also permits for enabling keep-alives on a connection while using the operating system default keep-alive configuration (setKeepAliveConfig.Enable, set the other fields to -1).
package net// KeepAliveConfig contains TCP keep-alive options.//// If the Idle, Interval, or Count fields are zero, a default value is chosen.// If a field is negative, the operating system default is used.type KeepAliveConfig struct { // If Enable is true, keep-alive probes are enabled. Enable bool // Idle is the time that the connection must be idle before // the first keep-alive probe is sent. Idle time.Duration // Interval is the time between keep-alive probes. Interval time.Duration // Count is the maximum number of keep-alive probes that // should be sent before dropping a connection. Count int}type Dialer { // contains existing unchanged fields // KeepAlive specifies the interval between keep-alive // probes for an active network connection. // // KeepAlive is ignored if KeepAliveConfig.Enable is true. // // If zero, keep-alive probes are sent with a default value // (currently 15 seconds), if supported by the protocol and operating // system. Network protocols or operating systems that do // not support keep-alives ignore this field. // If negative and KeepAliveConfig.Enable is false, keep-alive probes are disabled. KeepAlive time.Duration // KeepAliveConfig specifies the keep-alive probe configuration // for an active network connection, when supported by the // protocol and operating system. // // If KeepAliveConfig.Enable is true, keep-alives probes are enabled. // If KeepAliveConfig.Enable is false and KeepAlive is negative, // keep-alive probes are disabled. KeepAliveConfig KeepAliveConfig}type ListenConfig { // same fields as Dialer above}// SetKeepAliveConfig configures keep-alive messages sent by the operating system.func (c *TCPConn) SetKeepAliveConfig(config KeepAliveConfig) error {}