Use HTTP keep-alive feature in HTTPClient class

Currently  HTTPClient creates a new TCP connection for each
API request. We could actually reuse created connections by
relying upon HTTP keep-alive feature.  That would enable us
to do a few queries in a row more efficiently.

Fixes bug 1170385.

Change-Id: Ie6d8fb9670938e3790017509a242630b67abd794
This commit is contained in:
Roman Podolyaka 2013-04-18 18:01:54 +03:00
parent dccdd02e48
commit 27e904af69
5 changed files with 23 additions and 21 deletions

View File

@ -103,6 +103,8 @@ class HTTPClient(object):
# have to set it up here on WARNING (its original level) # have to set it up here on WARNING (its original level)
# otherwise we will get all the requests logging messanges # otherwise we will get all the requests logging messanges
rql.setLevel(logging.WARNING) rql.setLevel(logging.WARNING)
# requests within the same session can reuse TCP connections from pool
self.http = requests.Session()
def use_token_cache(self, use_it): def use_token_cache(self, use_it):
self.os_cache = use_it self.os_cache = use_it
@ -161,7 +163,7 @@ class HTTPClient(object):
kwargs.setdefault('timeout', self.timeout) kwargs.setdefault('timeout', self.timeout)
self.http_log_req((url, method,), kwargs) self.http_log_req((url, method,), kwargs)
resp = requests.request( resp = self.http.request(
method, method,
url, url,
verify=self.verify_cert, verify=self.verify_cert,

View File

@ -92,7 +92,7 @@ class DeprecatedAuthPluginTest(utils.TestCase):
@mock.patch.object(pkg_resources, "iter_entry_points", @mock.patch.object(pkg_resources, "iter_entry_points",
mock_iter_entry_points) mock_iter_entry_points)
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
plugin = auth_plugin.DeprecatedAuthPlugin("fake") plugin = auth_plugin.DeprecatedAuthPlugin("fake")
cs = client.Client("username", "password", "project_id", cs = client.Client("username", "password", "project_id",
@ -121,7 +121,7 @@ class DeprecatedAuthPluginTest(utils.TestCase):
@mock.patch.object(pkg_resources, "iter_entry_points", @mock.patch.object(pkg_resources, "iter_entry_points",
mock_iter_entry_points) mock_iter_entry_points)
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
auth_plugin.discover_auth_systems() auth_plugin.discover_auth_systems()
plugin = auth_plugin.DeprecatedAuthPlugin("notexists") plugin = auth_plugin.DeprecatedAuthPlugin("notexists")
@ -164,7 +164,7 @@ class DeprecatedAuthPluginTest(utils.TestCase):
@mock.patch.object(pkg_resources, "iter_entry_points", @mock.patch.object(pkg_resources, "iter_entry_points",
mock_iter_entry_points) mock_iter_entry_points)
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl") plugin = auth_plugin.DeprecatedAuthPlugin("fakewithauthurl")
cs = client.Client("username", "password", "project_id", cs = client.Client("username", "password", "project_id",
@ -197,7 +197,7 @@ class DeprecatedAuthPluginTest(utils.TestCase):
class AuthPluginTest(utils.TestCase): class AuthPluginTest(utils.TestCase):
@mock.patch.object(requests, "request") @mock.patch.object(requests.Session, "request")
@mock.patch.object(pkg_resources, "iter_entry_points") @mock.patch.object(pkg_resources, "iter_entry_points")
def test_auth_system_success(self, mock_iter_entry_points, mock_request): def test_auth_system_success(self, mock_iter_entry_points, mock_request):
"""Test that we can authenticate using the auth system.""" """Test that we can authenticate using the auth system."""

View File

@ -38,12 +38,12 @@ class ClientTest(utils.TestCase):
'x-server-management-url': 'blah.com', 'x-server-management-url': 'blah.com',
'x-auth-token': 'blah', 'x-auth-token': 'blah',
} }
with mock.patch('requests.request', mock_request): with mock.patch('requests.Session.request', mock_request):
instance.authenticate() instance.authenticate()
requests.request.assert_called_with(mock.ANY, mock.ANY, requests.Session.request.assert_called_with(mock.ANY, mock.ANY,
timeout=2, timeout=2,
headers=mock.ANY, headers=mock.ANY,
verify=mock.ANY) verify=mock.ANY)
def test_get_client_class_v2(self): def test_get_client_class_v2(self):
output = novaclient.client.get_client_class('2') output = novaclient.client.get_client_class('2')

View File

@ -43,7 +43,7 @@ class ClientTest(utils.TestCase):
def test_get(self): def test_get(self):
cl = get_authed_client() cl = get_authed_client()
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
@mock.patch('time.time', mock.Mock(return_value=1234)) @mock.patch('time.time', mock.Mock(return_value=1234))
def test_get_call(): def test_get_call():
resp, body = cl.get("/hi") resp, body = cl.get("/hi")
@ -65,7 +65,7 @@ class ClientTest(utils.TestCase):
def test_post(self): def test_post(self):
cl = get_authed_client() cl = get_authed_client()
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_post_call(): def test_post_call():
cl.post("/hi", body=[1, 2, 3]) cl.post("/hi", body=[1, 2, 3])
headers = { headers = {
@ -88,7 +88,7 @@ class ClientTest(utils.TestCase):
cl = get_client() cl = get_client()
# response must not have x-server-management-url header # response must not have x-server-management-url header
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate) self.assertRaises(exceptions.AuthorizationFailure, cl.authenticate)
@ -97,7 +97,7 @@ class ClientTest(utils.TestCase):
def test_connection_refused(self): def test_connection_refused(self):
cl = get_client() cl = get_client()
@mock.patch.object(requests, "request", refused_mock_request) @mock.patch.object(requests.Session, "request", refused_mock_request)
def test_refused_call(): def test_refused_call():
self.assertRaises(exceptions.ConnectionRefused, cl.get, "/hi") self.assertRaises(exceptions.ConnectionRefused, cl.get, "/hi")
@ -106,7 +106,7 @@ class ClientTest(utils.TestCase):
def test_bad_request(self): def test_bad_request(self):
cl = get_client() cl = get_client()
@mock.patch.object(requests, "request", bad_req_mock_request) @mock.patch.object(requests.Session, "request", bad_req_mock_request)
def test_refused_call(): def test_refused_call():
self.assertRaises(exceptions.BadRequest, cl.get, "/hi") self.assertRaises(exceptions.BadRequest, cl.get, "/hi")

View File

@ -44,7 +44,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
mock_request = mock.Mock(return_value=(auth_response)) mock_request = mock.Mock(return_value=(auth_response))
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
cs.client.authenticate() cs.client.authenticate()
headers = { headers = {
@ -90,7 +90,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
mock_request = mock.Mock(return_value=(auth_response)) mock_request = mock.Mock(return_value=(auth_response))
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) self.assertRaises(exceptions.Unauthorized, cs.client.authenticate)
@ -147,7 +147,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
mock_request = mock.Mock(side_effect=side_effect) mock_request = mock.Mock(side_effect=side_effect)
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
cs.client.authenticate() cs.client.authenticate()
headers = { headers = {
@ -230,7 +230,7 @@ class AuthenticateAgainstKeystoneTests(utils.TestCase):
mock_request = mock.Mock(return_value=(auth_response)) mock_request = mock.Mock(return_value=(auth_response))
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
self.assertRaises(exceptions.AmbiguousEndpoints, self.assertRaises(exceptions.AmbiguousEndpoints,
cs.client.authenticate) cs.client.authenticate)
@ -251,7 +251,7 @@ class AuthenticationTests(utils.TestCase):
}) })
mock_request = mock.Mock(return_value=(auth_response)) mock_request = mock.Mock(return_value=(auth_response))
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
cs.client.authenticate() cs.client.authenticate()
headers = { headers = {
@ -279,7 +279,7 @@ class AuthenticationTests(utils.TestCase):
auth_response = utils.TestResponse({'status_code': 401}) auth_response = utils.TestResponse({'status_code': 401})
mock_request = mock.Mock(return_value=(auth_response)) mock_request = mock.Mock(return_value=(auth_response))
@mock.patch.object(requests, "request", mock_request) @mock.patch.object(requests.Session, "request", mock_request)
def test_auth_call(): def test_auth_call():
self.assertRaises(exceptions.Unauthorized, cs.client.authenticate) self.assertRaises(exceptions.Unauthorized, cs.client.authenticate)