From c259a8ea387773ce6d0fde449cc38e3b737532cd Mon Sep 17 00:00:00 2001 From: Anis Eleuch Date: Fri, 24 Mar 2023 16:10:58 +0100 Subject: [PATCH] Set tcp user timeout to clean sockets with data in the buffer (#16887) --- internal/http/dial_linux.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/internal/http/dial_linux.go b/internal/http/dial_linux.go index 2ced89899..7d61cae1c 100644 --- a/internal/http/dial_linux.go +++ b/internal/http/dial_linux.go @@ -51,6 +51,24 @@ func setTCPParameters(network, address string, c syscall.RawConn) error { // Enable TCP quick ACK, John Nagle says // "Set TCP_QUICKACK. If you find a case where that makes things worse, let me know." _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, unix.TCP_QUICKACK, 1) + + // The time (in seconds) the connection needs to remain idle before + // TCP starts sending keepalive probes + _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, 15) + + // Number of probes. + // ~ cat /proc/sys/net/ipv4/tcp_keepalive_probes (defaults to 9, we reduce it to 5) + _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPCNT, 5) + + // Wait time after successful probe in seconds. + // ~ cat /proc/sys/net/ipv4/tcp_keepalive_intvl (defaults to 75 secs, we reduce it to 15 secs) + _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, 15) + + // Set tcp user timeout in addition to the keep-alive - tcp-keepalive is not enough to close a socket + // with dead end because tcp-keepalive is not fired when there is data in the socket buffer. + // https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/ + // This is a sensitive configuration, it is better to set it to high values, > 60 secs + _ = syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, (15+5*15)*1000) }) return nil }