From 53772f5320f964e98dba3d54ac645bf8075637d1 Mon Sep 17 00:00:00 2001 From: Michael Johnson Date: Thu, 30 Aug 2018 15:14:23 -0700 Subject: [PATCH] Set some amphora driver optimizations This patch adds a few optimizations when using the amphora driver. 1. It increases the amp_active_retries from 10 to 30. This increases the time we wait for nova to mark an instance "ACTIVE". The old default of 10 was one minute forty seconds, but in some clouds it's been observed that the nova schedule can get overloaded and take longer than a minute forty to schedule the instance. Setting this to 30 means we will wait five minutes for nova to schedule the instance. 2. It enables TCP kernel splicing in HAProxy. This has been shown to reduce the CPU overhead for very high rate TCP load balancers. 3. Finally it enables "safe" HTTP keepalives on the backend member connections [1]. This increases the request rate possible while using HTTP protocol listeners and members. [1] http://cbonte.github.io/haproxy-dconv/1.6/configuration.html#4-http-reuse Change-Id: I3af009cac9a9edc8aef793b52c6a1488fde2c59b --- etc/octavia.conf | 2 +- octavia/common/config.py | 2 +- .../common/jinja/haproxy/templates/base.j2 | 3 +++ .../common/jinja/haproxy/templates/macros.j2 | 6 +++++ .../api_server/test_haproxy_compatibility.py | 5 +++- .../common/jinja/haproxy/test_jinja_cfg.py | 23 ++++++++++++++++++- .../common/sample_configs/sample_configs.py | 6 ++++- 7 files changed, 42 insertions(+), 5 deletions(-) diff --git a/etc/octavia.conf b/etc/octavia.conf index ec8900280e..ef90c9f6b2 100644 --- a/etc/octavia.conf +++ b/etc/octavia.conf @@ -210,7 +210,7 @@ [controller_worker] # workers = 1 -# amp_active_retries = 10 +# amp_active_retries = 30 # amp_active_wait_sec = 10 # Glance parameters to extract image ID to use for amphora. Only one of # parameters is needed. Using tags is the recommended way to refer to images. diff --git a/octavia/common/config.py b/octavia/common/config.py index 41889a5326..25d8cdf069 100644 --- a/octavia/common/config.py +++ b/octavia/common/config.py @@ -315,7 +315,7 @@ controller_worker_opts = [ default=1, min=1, help='Number of workers for the controller-worker service.'), cfg.IntOpt('amp_active_retries', - default=10, + default=30, help=_('Retry attempts to wait for Amphora to become active')), cfg.IntOpt('amp_active_wait_sec', default=10, diff --git a/octavia/common/jinja/haproxy/templates/base.j2 b/octavia/common/jinja/haproxy/templates/base.j2 index 40f9313b77..b94e800714 100644 --- a/octavia/common/jinja/haproxy/templates/base.j2 +++ b/octavia/common/jinja/haproxy/templates/base.j2 @@ -41,6 +41,9 @@ defaults {% endif %} retries 3 option redispatch + option splice-request + option splice-response + option http-keep-alive {% block peers %}{% endblock peers %} diff --git a/octavia/common/jinja/haproxy/templates/macros.j2 b/octavia/common/jinja/haproxy/templates/macros.j2 index cb11d2c0d7..f74954609a 100644 --- a/octavia/common/jinja/haproxy/templates/macros.j2 +++ b/octavia/common/jinja/haproxy/templates/macros.j2 @@ -203,6 +203,12 @@ backend {{ pool.id }} {% else %} mode {{ pool.protocol }} {% endif %} + {% if (pool.protocol.lower() == constants.PROTOCOL_HTTP.lower() or + (pool.protocol.lower() == constants.PROTOCOL_PROXY.lower() and + listener.protocol_mode.lower() == + constants.PROTOCOL_HTTP.lower()))%} + http-reuse safe + {% endif %} balance {{ pool.lb_algorithm }} {% if pool.session_persistence %} {% if (pool.session_persistence.type == diff --git a/octavia/tests/unit/amphorae/backends/agent/api_server/test_haproxy_compatibility.py b/octavia/tests/unit/amphorae/backends/agent/api_server/test_haproxy_compatibility.py index bfdaa49e6c..c457532e37 100644 --- a/octavia/tests/unit/amphorae/backends/agent/api_server/test_haproxy_compatibility.py +++ b/octavia/tests/unit/amphorae/backends/agent/api_server/test_haproxy_compatibility.py @@ -36,7 +36,10 @@ class HAProxyCompatTestCase(base.TestCase): "defaults\n" " log global\n" " retries 3\n" - " option redispatch\n\n\n\n" + " option redispatch\n" + " option splice-request\n" + " option splice-response\n" + " option http-keep-alive\n\n\n\n" "frontend sample_listener_id_1\n" " option httplog\n" " maxconn {maxconn}\n" diff --git a/octavia/tests/unit/common/jinja/haproxy/test_jinja_cfg.py b/octavia/tests/unit/common/jinja/haproxy/test_jinja_cfg.py index afcded7d7d..37c3e41ed8 100644 --- a/octavia/tests/unit/common/jinja/haproxy/test_jinja_cfg.py +++ b/octavia/tests/unit/common/jinja/haproxy/test_jinja_cfg.py @@ -45,6 +45,7 @@ class TestHaproxyCfg(base.TestCase): maxconn=constants.HAPROXY_MAX_MAXCONN) be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -89,6 +90,7 @@ class TestHaproxyCfg(base.TestCase): maxconn=constants.HAPROXY_MAX_MAXCONN) be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -122,6 +124,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_http(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -148,6 +151,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_member_backup(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -185,6 +189,7 @@ class TestHaproxyCfg(base.TestCase): maxconn=constants.HAPROXY_MAX_MAXCONN) be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -221,6 +226,7 @@ class TestHaproxyCfg(base.TestCase): maxconn=constants.HAPROXY_MAX_MAXCONN) be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -249,6 +255,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_member_monitor_addr_port(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -343,6 +350,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_no_monitor_http(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " fullconn {maxconn}\n" @@ -363,6 +371,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_disabled_member(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " fullconn {maxconn}\n" @@ -384,6 +393,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_ping_monitor_http(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -466,6 +476,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_no_persistence_http(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " fullconn {maxconn}\n" " option allbackups\n" @@ -484,6 +495,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_sourceip_persistence(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " stick-table type ip size 10k\n" " stick on src\n" @@ -510,6 +522,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_appcookie_persistence(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " stick-table type string len 64 size 10k\n" " stick store-response res.cook(JSESSIONID)\n" @@ -615,6 +628,7 @@ class TestHaproxyCfg(base.TestCase): maxconn=constants.HAPROXY_MAX_MAXCONN) be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -631,6 +645,7 @@ class TestHaproxyCfg(base.TestCase): "\n" "backend sample_pool_id_2\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -652,6 +667,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_http_xff(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -680,6 +696,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_http_xff_xfport(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -710,6 +727,7 @@ class TestHaproxyCfg(base.TestCase): def test_render_template_pool_proxy_protocol(self): be = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -852,7 +870,10 @@ class TestHaproxyCfg(base.TestCase): defaults = ("defaults\n" " no log\n" " retries 3\n" - " option redispatch\n\n") + " option redispatch\n" + " option splice-request\n" + " option splice-response\n" + " option http-keep-alive\n\n") rendered_obj = j_cfg.render_loadbalancer_obj( sample_configs.sample_amphora_tuple(), sample_configs.sample_listener_tuple() diff --git a/octavia/tests/unit/common/sample_configs/sample_configs.py b/octavia/tests/unit/common/sample_configs/sample_configs.py index 550e1f8153..41d2477009 100644 --- a/octavia/tests/unit/common/sample_configs/sample_configs.py +++ b/octavia/tests/unit/common/sample_configs/sample_configs.py @@ -839,6 +839,7 @@ def sample_base_expected_config(frontend=None, backend=None, if backend is None: backend = ("backend sample_pool_id_1\n" " mode http\n" + " http-reuse safe\n" " balance roundrobin\n" " cookie SRV insert indirect nocache\n" " timeout check 31s\n" @@ -863,7 +864,10 @@ def sample_base_expected_config(frontend=None, backend=None, defaults = ("defaults\n" " log global\n" " retries 3\n" - " option redispatch\n\n") + " option redispatch\n" + " option splice-request\n" + " option splice-response\n" + " option http-keep-alive\n\n") return ("# Configuration for loadbalancer sample_loadbalancer_id_1\n" "global\n" " daemon\n"