Configure TCP Keep-Alive for certain Sessions
If the user creates a keystoneclient.session.Session without passing a custom session, we will enable TCP Keep-Alive for the requests session used by keystoneclient's Session. novaclient and other clients can experience hung TCP connections. Most clients use keystoneclient's session and will need this merged here before they can make use of it in their projects. Change-Id: Ib70a8b3270d2492596b9fb8981b8584b85567a9c Closes-bug: 1323862
This commit is contained in:
@@ -15,6 +15,7 @@ import functools
|
|||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
@@ -123,6 +124,9 @@ class Session(object):
|
|||||||
redirect=_DEFAULT_REDIRECT_LIMIT):
|
redirect=_DEFAULT_REDIRECT_LIMIT):
|
||||||
if not session:
|
if not session:
|
||||||
session = requests.Session()
|
session = requests.Session()
|
||||||
|
# Use TCPKeepAliveAdapter to fix bug 1323862
|
||||||
|
for scheme in session.adapters.keys():
|
||||||
|
session.mount(scheme, TCPKeepAliveAdapter())
|
||||||
|
|
||||||
self.auth = auth
|
self.auth = auth
|
||||||
self.session = session
|
self.session = session
|
||||||
@@ -778,3 +782,14 @@ class Session(object):
|
|||||||
kwargs['timeout'] = args.timeout
|
kwargs['timeout'] = args.timeout
|
||||||
|
|
||||||
return cls._make(**kwargs)
|
return cls._make(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TCPKeepAliveAdapter(requests.adapters.HTTPAdapter):
|
||||||
|
"""The custom adapter used to set TCP Keep-Alive on all connections."""
|
||||||
|
def init_poolmanager(self, *args, **kwargs):
|
||||||
|
if requests.__version__ >= '2.4.1':
|
||||||
|
kwargs.setdefault('socket_options', [
|
||||||
|
(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),
|
||||||
|
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
|
||||||
|
])
|
||||||
|
super(TCPKeepAliveAdapter, self).init_poolmanager(*args, **kwargs)
|
||||||
|
@@ -205,6 +205,19 @@ class SessionTests(utils.TestCase):
|
|||||||
self.assertThat(self.requests.request_history,
|
self.assertThat(self.requests.request_history,
|
||||||
matchers.HasLength(retries + 1))
|
matchers.HasLength(retries + 1))
|
||||||
|
|
||||||
|
def test_uses_tcp_keepalive_by_default(self):
|
||||||
|
session = client_session.Session()
|
||||||
|
requests_session = session.session
|
||||||
|
self.assertIsInstance(requests_session.adapters['http://'],
|
||||||
|
client_session.TCPKeepAliveAdapter)
|
||||||
|
self.assertIsInstance(requests_session.adapters['https://'],
|
||||||
|
client_session.TCPKeepAliveAdapter)
|
||||||
|
|
||||||
|
def test_does_not_set_tcp_keepalive_on_custom_sessions(self):
|
||||||
|
mock_session = mock.Mock()
|
||||||
|
client_session.Session(session=mock_session)
|
||||||
|
self.assertFalse(mock_session.mount.called)
|
||||||
|
|
||||||
|
|
||||||
class RedirectTests(utils.TestCase):
|
class RedirectTests(utils.TestCase):
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user