haproxy ns driver: set global haproxy maxconn
Haproxy uses two separate maxconn values: the maxconn setting in the global context is used to adjust file descriptor limits and allocate resources, while the maxconn setting in the frontend context controls if additional connections are accepted on that frontend. This patch adds a maxconn to the global context equal to the sum of the connection limit on each listener. For listeners which no connection limit specified, the haproxy default global connection limit (2000 connections) is used. This way we provide the same behavior as a default haproxy configuraiton which no connection limit specified in the case of a single load balancer. Change-Id: Icc63771ed15a7f718dab0389c1fb63d628896e0a Partial-Bug: 1544861
This commit is contained in:
parent
195d3a6f8f
commit
a792d8906c
@ -248,14 +248,25 @@ def _transform_loadbalancer(loadbalancer, haproxy_base_dir):
|
|||||||
listeners = [_transform_listener(x, haproxy_base_dir)
|
listeners = [_transform_listener(x, haproxy_base_dir)
|
||||||
for x in loadbalancer.listeners if x.admin_state_up]
|
for x in loadbalancer.listeners if x.admin_state_up]
|
||||||
pools = [_transform_pool(x) for x in loadbalancer.pools]
|
pools = [_transform_pool(x) for x in loadbalancer.pools]
|
||||||
|
connection_limit = _compute_global_connection_limit(listeners)
|
||||||
return {
|
return {
|
||||||
'name': loadbalancer.name,
|
'name': loadbalancer.name,
|
||||||
'vip_address': loadbalancer.vip_address,
|
'vip_address': loadbalancer.vip_address,
|
||||||
|
'connection_limit': connection_limit,
|
||||||
'listeners': listeners,
|
'listeners': listeners,
|
||||||
'pools': pools
|
'pools': pools
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _compute_global_connection_limit(listeners):
|
||||||
|
# NOTE(dlundquist): HAProxy has a global default connection limit
|
||||||
|
# of 2000, so we will include 2000 connections for each listener
|
||||||
|
# without a connection limit specified. This way we provide the
|
||||||
|
# same behavior as a default haproxy configuration without
|
||||||
|
# connection limit specified in the case of a single load balancer.
|
||||||
|
return sum([x.get('connection_limit', 2000) for x in listeners])
|
||||||
|
|
||||||
|
|
||||||
def _transform_listener(listener, haproxy_base_dir):
|
def _transform_listener(listener, haproxy_base_dir):
|
||||||
"""Transforms listener object
|
"""Transforms listener object
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
{% set loadbalancer_name = loadbalancer.name %}
|
{% set loadbalancer_name = loadbalancer.name %}
|
||||||
{% set usergroup = user_group %}
|
{% set usergroup = user_group %}
|
||||||
{% set sock_path = stats_sock %}
|
{% set sock_path = stats_sock %}
|
||||||
|
{% set connection_limit = loadbalancer.connection_limit %}
|
||||||
|
|
||||||
{% block proxies %}
|
{% block proxies %}
|
||||||
{% from 'haproxy_proxies.j2' import frontend_macro as frontend_macro, backend_macro%}
|
{% from 'haproxy_proxies.j2' import frontend_macro as frontend_macro, backend_macro%}
|
||||||
|
@ -20,6 +20,7 @@ global
|
|||||||
group {{ usergroup }}
|
group {{ usergroup }}
|
||||||
log /dev/log local0
|
log /dev/log local0
|
||||||
log /dev/log local1 notice
|
log /dev/log local1 notice
|
||||||
|
maxconn {{ connection_limit }}
|
||||||
stats socket {{ sock_path }} mode 0666 level user
|
stats socket {{ sock_path }} mode 0666 level user
|
||||||
|
|
||||||
defaults
|
defaults
|
||||||
|
@ -102,18 +102,21 @@ RET_LB = {
|
|||||||
'name': 'test-lb',
|
'name': 'test-lb',
|
||||||
'vip_address': '10.0.0.2',
|
'vip_address': '10.0.0.2',
|
||||||
'listeners': [RET_LISTENER],
|
'listeners': [RET_LISTENER],
|
||||||
|
'connection_limit': RET_LISTENER['connection_limit'],
|
||||||
'pools': [RET_POOL]}
|
'pools': [RET_POOL]}
|
||||||
|
|
||||||
RET_LB_TLS = {
|
RET_LB_TLS = {
|
||||||
'name': 'test-lb',
|
'name': 'test-lb',
|
||||||
'vip_address': '10.0.0.2',
|
'vip_address': '10.0.0.2',
|
||||||
'listeners': [RET_LISTENER_TLS],
|
'listeners': [RET_LISTENER_TLS],
|
||||||
|
'connection_limit': RET_LISTENER_TLS['connection_limit'],
|
||||||
'pools': [RET_POOL]}
|
'pools': [RET_POOL]}
|
||||||
|
|
||||||
RET_LB_TLS_SNI = {
|
RET_LB_TLS_SNI = {
|
||||||
'name': 'test-lb',
|
'name': 'test-lb',
|
||||||
'vip_address': '10.0.0.2',
|
'vip_address': '10.0.0.2',
|
||||||
'listeners': [RET_LISTENER_TLS_SNI],
|
'listeners': [RET_LISTENER_TLS_SNI],
|
||||||
|
'connection_limit': RET_LISTENER_TLS_SNI['connection_limit'],
|
||||||
'pools': [RET_POOL]}
|
'pools': [RET_POOL]}
|
||||||
|
|
||||||
|
|
||||||
@ -148,7 +151,8 @@ def sample_vip_port_tuple():
|
|||||||
|
|
||||||
|
|
||||||
def sample_listener_tuple(proto=None, monitor=True, persistence=True,
|
def sample_listener_tuple(proto=None, monitor=True, persistence=True,
|
||||||
persistence_type=None, tls=False, sni=False):
|
persistence_type=None, tls=False, sni=False,
|
||||||
|
connection_limit=98):
|
||||||
proto = 'HTTP' if proto is None else proto
|
proto = 'HTTP' if proto is None else proto
|
||||||
port = '443' if proto is 'HTTPS' or proto is 'TERMINATED_HTTPS' else '80'
|
port = '443' if proto is 'HTTPS' or proto is 'TERMINATED_HTTPS' else '80'
|
||||||
in_listener = collections.namedtuple(
|
in_listener = collections.namedtuple(
|
||||||
@ -164,7 +168,7 @@ def sample_listener_tuple(proto=None, monitor=True, persistence=True,
|
|||||||
default_pool=sample_pool_tuple(
|
default_pool=sample_pool_tuple(
|
||||||
proto=proto, monitor=monitor, persistence=persistence,
|
proto=proto, monitor=monitor, persistence=persistence,
|
||||||
persistence_type=persistence_type),
|
persistence_type=persistence_type),
|
||||||
connection_limit=98,
|
connection_limit=connection_limit,
|
||||||
admin_state_up=True,
|
admin_state_up=True,
|
||||||
default_tls_container_id='cont_id_1' if tls else '',
|
default_tls_container_id='cont_id_1' if tls else '',
|
||||||
sni_container_ids=['cont_id_2', 'cont_id_3'] if sni else [],
|
sni_container_ids=['cont_id_2', 'cont_id_3'] if sni else [],
|
||||||
@ -284,6 +288,7 @@ def sample_base_expected_config(backend, frontend=None):
|
|||||||
" group nogroup\n"
|
" group nogroup\n"
|
||||||
" log /dev/log local0\n"
|
" log /dev/log local0\n"
|
||||||
" log /dev/log local1 notice\n"
|
" log /dev/log local1 notice\n"
|
||||||
|
" maxconn 98\n"
|
||||||
" stats socket /sock_path mode 0666 level user\n\n"
|
" stats socket /sock_path mode 0666 level user\n\n"
|
||||||
"defaults\n"
|
"defaults\n"
|
||||||
" log global\n"
|
" log global\n"
|
||||||
|
@ -447,6 +447,14 @@ class TestHaproxyCfg(base.BaseTestCase):
|
|||||||
ret = jinja_cfg._transform_loadbalancer(in_lb, '/v2')
|
ret = jinja_cfg._transform_loadbalancer(in_lb, '/v2')
|
||||||
self.assertEqual(sample_configs.RET_LB, ret)
|
self.assertEqual(sample_configs.RET_LB, ret)
|
||||||
|
|
||||||
|
def test_compute_global_connection_limit(self):
|
||||||
|
lts = [
|
||||||
|
sample_configs.sample_listener_tuple(connection_limit=None),
|
||||||
|
sample_configs.sample_listener_tuple()]
|
||||||
|
in_listeners = [jinja_cfg._transform_listener(x, '/v2') for x in lts]
|
||||||
|
ret = jinja_cfg._compute_global_connection_limit(in_listeners)
|
||||||
|
self.assertEqual(2098, ret)
|
||||||
|
|
||||||
def test_include_member(self):
|
def test_include_member(self):
|
||||||
ret = jinja_cfg._include_member(
|
ret = jinja_cfg._include_member(
|
||||||
sample_configs.sample_member_tuple('sample_member_id_1',
|
sample_configs.sample_member_tuple('sample_member_id_1',
|
||||||
|
Loading…
Reference in New Issue
Block a user