Set reasonable defaults for TCP Keep-Alive

Previously we simply turned on TCP Keep-Alive which relied on
per-distribution, per-operating system defaults for keep-alive options.
Here we set reasonable defaults since long running processes can get
stuck for hours on end by using system defaults. This also adds comments
around the options to explain why they're being set.

Closes-bug: 1477275
Related-bug: 1323862
Change-Id: Id7d5cb4d5c7012514359e33ce58992cc0830c4e8
This commit is contained in:
Ian Cordasco 2015-07-23 15:18:05 -05:00
parent 0120a214ab
commit 4b09541461

View File

@ -900,11 +900,36 @@ class Session(object):
class TCPKeepAliveAdapter(requests.adapters.HTTPAdapter):
"""The custom adapter used to set TCP Keep-Alive on all connections."""
"""The custom adapter used to set TCP Keep-Alive on all connections.
This Adapter also preserves the default behaviour of Requests which
disables Nagle's Algorithm. See also:
http://blogs.msdn.com/b/windowsazurestorage/archive/2010/06/25/nagle-s-algorithm-is-not-friendly-towards-small-requests.aspx
"""
def init_poolmanager(self, *args, **kwargs):
if requests.__version__ >= '2.4.1':
kwargs.setdefault('socket_options', [
socket_options = [
# Keep Nagle's algorithm off
(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),
# Turn on TCP Keep-Alive
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
])
# Set the maximum number of keep-alive probes
(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, 4),
# Send keep-alive probes every 15 seconds
(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, 15),
]
# Some operating systems (e.g., OSX) do not support setting
# keepidle
if hasattr(socket, 'TCP_KEEPIDLE'):
socket_options += [
# Wait 60 seconds before sending keep-alive probes
(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, 60)
]
# After waiting 60 seconds, and then sending a probe once every 15
# seconds 4 times, these options should ensure that a connection
# hands for no longer than 2 minutes before a ConnectionError is
# raised.
kwargs.setdefault('socket_options', socket_options)
super(TCPKeepAliveAdapter, self).init_poolmanager(*args, **kwargs)