Skip to content

Commit afb3b0b

Browse files
committed
Enable TCP keep alive on HTTP socket level
This commit changes the socket options of a connection in a way that keepalive (socket.SO_KEEPALIVE) is enabled by default. If enabled, the kernel settings can be overwritten by individual options. Setting the socket options is still handled by urllib3. Reference: https://urllib3.readthedocs.io/en/latest/reference/urllib3.connection.html#urllib3.connection.HTTPConnection The new arguments for `crate.client.connect` and respectively `crate.client.connection.Connection` are: * `socket_keepalive`: (optional, defaults to ``True``) Enable TCP keepalive on socket level. * `socket_tcp_keepidle`: (optional) Set the `TCP_KEEPIDLE` socket option, which overrides `net.ipv4.tcp_keepalive_time` kernel setting if `socket_keepalive` is `True`. * `socket_tcp_keepintvl`: (optional) Set the `TCP_KEEPINTVL` socket option, which overrides `net.ipv4.tcp_keepalive_intvl` kernel setting if `socket_keepalive` is `True`. * `socket_tcp_keepcnt`: (optional) Set the `TCP_KEEPCNT` socket option, which overrides `net.ipv4.tcp_keepalive_probes` kernel setting if `socket_keepalive` is `True`.
1 parent 89f3c22 commit afb3b0b

File tree

7 files changed

+207
-97
lines changed

7 files changed

+207
-97
lines changed

CHANGES.txt

+7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@ Changes for crate
55
Unreleased
66
==========
77

8+
- Enabled TCP keepalive on socket level and support for setting socket options
9+
when creating the connection. The supported options are:
10+
11+
- ``TCP_KEEPIDLE`` (overriding ``net.ipv4.tcp_keepalive_time``)
12+
- ``TCP_KEEPINTVL`` (overriding ``net.ipv4.tcp_keepalive_intvl``)
13+
- ``TCP_KEEPCNT`` (overriding ``net.ipv4.tcp_keepalive_probes``)
14+
815
- Propagate connect parameter ``pool_size`` to urllib3 as ``maxsize`` parameter
916
in order to make the connection pool size configurable.
1017

docs/connect.rst

+36-4
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,51 @@ the optional ``error_trace`` argument to ``True``, like so::
167167

168168
>>> connection = client.connect(..., error_trace=True)
169169

170-
.. _authentication:
171-
172170
Backoff Factor
173-
..............
171+
--------------
174172

175173
When attempting to make a request, the connection can be configured so that
176174
retries are made in increasing time intervals. This can be configured like so::
177175

178176
>>> connection = client.connect(..., backoff_factor=0.1)
179177

180-
If ``backoff_factor``is set to 0.1, then the delay between retries will be 0.0,
178+
If ``backoff_factor`` is set to 0.1, then the delay between retries will be 0.0,
181179
0.1, 0.2, 0.4 etc. The maximum backoff factor cannot exceed 120 seconds and by
182180
default its value is 0.
183181

182+
Socket Options
183+
--------------
184+
185+
Creating connections uses `urllib3 default socket options`_ but additionally
186+
enables TCP keepalive by setting ``socket.SO_KEEPALIVE`` to ``1``.
187+
188+
Keepalive can be disabled using the ``socket_keepalive`` argument, like so::
189+
190+
>>> connection = client.connect(..., socket_keepalive=False)
191+
192+
If keepalive is enabled (default), there are three additional, optional socket
193+
options that can be configured via connection arguments.
194+
195+
:``socket_tcp_keepidle``:
196+
197+
Set the ``TCP_KEEPIDLE`` socket option, which overrides
198+
``net.ipv4.tcp_keepalive_time`` kernel setting if ``socket_keepalive`` is
199+
``True``.
200+
201+
:``socket_tcp_keepintvl``:
202+
203+
Set the ``TCP_KEEPINTVL`` socket option, which overrides
204+
``net.ipv4.tcp_keepalive_intvl`` kernel setting if ``socket_keepalive`` is
205+
``True``.
206+
207+
:``socket_tcp_keepcnt``:
208+
209+
Set the ``TCP_KEEPCNT`` socket option, which overrides
210+
``net.ipv4.tcp_keepalive_probes`` kernel setting if ``socket_keepalive`` is
211+
``True``.
212+
213+
.. _authentication:
214+
184215
Authentication
185216
==============
186217

@@ -247,3 +278,4 @@ Once you're connected, you can :ref:`query CrateDB <query>`.
247278
.. _socket timeout: https://docs.python.org/2/library/socket.html#socket.getdefaulttimeout
248279
.. _SQLAlchemy: http://www.sqlalchemy.org/
249280
.. _tracebacks: https://docs.python.org/3/library/traceback.html
281+
.. _urllib3 default socket options: https://urllib3.readthedocs.io/en/latest/reference/urllib3.connection.html#urllib3.connection.HTTPConnection

src/crate/client/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
# with Crate these terms will supersede the license and you may use the
2020
# software solely pursuant to the terms of the relevant commercial agreement.
2121

22-
from .connection import connect
22+
from .connection import Connection as connect
2323
from .exceptions import Error
2424

2525
__all__ = [

src/crate/client/connection.py

+67-66
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,65 @@ def __init__(self,
4141
username=None,
4242
password=None,
4343
schema=None,
44-
pool_size=None):
44+
pool_size=None,
45+
socket_keepalive=True,
46+
socket_tcp_keepidle=None,
47+
socket_tcp_keepintvl=None,
48+
socket_tcp_keepcnt=None,
49+
):
50+
"""
51+
:param servers:
52+
either a string in the form of '<hostname>:<port>'
53+
or a list of servers in the form of ['<hostname>:<port>', '...']
54+
:param timeout:
55+
(optional)
56+
define the retry timeout for unreachable servers in seconds
57+
:param backoff_factor:
58+
(optional)
59+
define the retry interval for unreachable servers in seconds
60+
:param client:
61+
(optional - for testing)
62+
client used to communicate with crate.
63+
:param verify_ssl_cert:
64+
if set to ``True`` verify the servers SSL server certificate.
65+
defaults to ``False``
66+
:param ca_cert:
67+
a path to a CA certificate to use when verifying the SSL server
68+
certificate.
69+
:param error_trace:
70+
if set to ``True`` return a whole stacktrace of any server error if
71+
one occurs
72+
:param cert_file:
73+
a path to the client certificate to present to the server.
74+
:param key_file:
75+
a path to the client key to use when communicating with the server.
76+
:param username:
77+
the username in the database.
78+
:param password:
79+
the password of the user in the database.
80+
:param pool_size:
81+
(optional)
82+
Number of connections to save that can be reused.
83+
More than 1 is useful in multithreaded situations.
84+
:param socket_keepalive:
85+
(optional, defaults to ``True``)
86+
Enable TCP keepalive on socket level.
87+
:param socket_tcp_keepidle:
88+
(optional)
89+
Set the ``TCP_KEEPIDLE`` socket option, which overrides
90+
``net.ipv4.tcp_keepalive_time`` kernel setting if ``socket_keepalive``
91+
is ``True``.
92+
:param socket_tcp_keepintvl:
93+
(optional)
94+
Set the ``TCP_KEEPINTVL`` socket option, which overrides
95+
``net.ipv4.tcp_keepalive_intvl`` kernel setting if ``socket_keepalive``
96+
is ``True``.
97+
:param socket_tcp_keepcnt:
98+
(optional)
99+
Set the ``TCP_KEEPCNT`` socket option, which overrides
100+
``net.ipv4.tcp_keepalive_probes`` kernel setting if ``socket_keepalive``
101+
is ``True``.
102+
"""
45103
if client:
46104
self.client = client
47105
else:
@@ -56,7 +114,12 @@ def __init__(self,
56114
username=username,
57115
password=password,
58116
schema=schema,
59-
pool_size=pool_size)
117+
pool_size=pool_size,
118+
socket_keepalive=socket_keepalive,
119+
socket_tcp_keepidle=socket_tcp_keepidle,
120+
socket_tcp_keepintvl=socket_tcp_keepintvl,
121+
socket_tcp_keepcnt=socket_tcp_keepcnt,
122+
)
60123
self.lowest_server_version = self._lowest_server_version()
61124
self._closed = False
62125

@@ -113,67 +176,5 @@ def __exit__(self, *excs):
113176
self.close()
114177

115178

116-
def connect(servers=None,
117-
timeout=None,
118-
backoff_factor=0,
119-
client=None,
120-
verify_ssl_cert=False,
121-
ca_cert=None,
122-
error_trace=False,
123-
cert_file=None,
124-
key_file=None,
125-
username=None,
126-
password=None,
127-
schema=None,
128-
pool_size=None):
129-
""" Create a :class:Connection object
130-
131-
:param servers:
132-
either a string in the form of '<hostname>:<port>'
133-
or a list of servers in the form of ['<hostname>:<port>', '...']
134-
:param timeout:
135-
(optional)
136-
define the retry timeout for unreachable servers in seconds
137-
:param backoff_factor:
138-
(optional)
139-
define the retry interval for unreachable servers in seconds
140-
:param client:
141-
(optional - for testing)
142-
client used to communicate with crate.
143-
:param verify_ssl_cert:
144-
if set to ``True`` verify the servers SSL server certificate.
145-
defaults to ``False``
146-
:param ca_cert:
147-
a path to a CA certificate to use when verifying the SSL server
148-
certificate.
149-
:param error_trace:
150-
if set to ``True`` return a whole stacktrace of any server error if
151-
one occurs
152-
:param cert_file:
153-
a path to the client certificate to present to the server.
154-
:param key_file:
155-
a path to the client key to use when communicating with the server.
156-
:param username:
157-
the username in the database.
158-
:param password:
159-
the password of the user in the database.
160-
:param pool_size:
161-
(optional)
162-
Number of connections to save that can be reused.
163-
More than 1 is useful in multithreaded situations.
164-
>>> connect(['host1:4200', 'host2:4200'])
165-
<Connection <Client ['http://host1:4200', 'http://host2:4200']>>
166-
"""
167-
return Connection(servers=servers,
168-
timeout=timeout,
169-
backoff_factor=backoff_factor,
170-
pool_size=pool_size,
171-
client=client,
172-
verify_ssl_cert=verify_ssl_cert,
173-
ca_cert=ca_cert,
174-
error_trace=error_trace,
175-
cert_file=cert_file,
176-
key_file=key_file,
177-
username=username,
178-
password=password,
179-
schema=schema)
179+
# For backwards compatibility and not to break existing imports
180+
connect = Connection

src/crate/client/doctests/blob.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ bloba API.
77

88
Create a connection::
99

10-
>>> from crate.client.connection import connect
10+
>>> from crate.client import connect
1111
>>> client = connect([crate_host])
1212

1313
Get a blob container::

0 commit comments

Comments
 (0)