Optimize HAProxy SSL cache size

If a HTTPS termination listener exists, set the tune.ssl.cachesize
setting to use about half of the available
memory (free + buffers + cached) on the amphora minus the memory needed
for network sockets based on the global max connections setting.
A larger SSL cache allows for more resumed SSL sessions and
therefore less computationally expensive SSL handshakes.

Change-Id: I87efba18017aa3e8b9b3cc812664efc11af1c4c4
This commit is contained in:
Tom Weininger 2022-08-18 10:54:45 +02:00
parent baefc3b464
commit 454cff587e
3 changed files with 34 additions and 0 deletions

View File

@ -187,6 +187,9 @@ class JinjaTemplater(object):
constants.INSECURE_FORK) constants.INSECURE_FORK)
enable_prometheus = prometheus_listener and feature_compatibility.get( enable_prometheus = prometheus_listener and feature_compatibility.get(
lib_consts.PROTOCOL_PROMETHEUS, False) lib_consts.PROTOCOL_PROMETHEUS, False)
term_https_listener = any(
lsnr.protocol == lib_consts.PROTOCOL_TERMINATED_HTTPS for lsnr in
listeners)
jinja_dict = { jinja_dict = {
'loadbalancer': loadbalancer, 'loadbalancer': loadbalancer,
@ -209,6 +212,25 @@ class JinjaTemplater(object):
except (KeyError, TypeError): except (KeyError, TypeError):
pass pass
if term_https_listener:
try:
mem = amp_details["memory"]
# Account for 32 KB per established connection for each
# pair of HAProxy network sockets. Use 1024 as fallback
# because that is what ulimit -n typically returns.
max_conn_mem_kb = 32 * loadbalancer.get(
"global_connection_limit", 1024)
# Use half of the remaining memory for SSL caches
ssl_cache_mem_kb = (mem["free"] + mem["buffers"] +
mem["cached"] - max_conn_mem_kb) // 2
# A cache block uses about 200 bytes of data.
# The HAProxy default of ssl_cache (20000) would take up
# 4000 KB. We don't want to go below that.
if ssl_cache_mem_kb > 4000:
jinja_dict["ssl_cache"] = ssl_cache_mem_kb * 5
except (KeyError, TypeError):
pass
return self._get_template().render( return self._get_template().render(
jinja_dict, constants=constants, lib_consts=lib_consts) jinja_dict, constants=constants, lib_consts=lib_consts)

View File

@ -26,6 +26,9 @@ global
{% if loadbalancer.global_connection_limit is defined %} {% if loadbalancer.global_connection_limit is defined %}
maxconn {{ loadbalancer.global_connection_limit }} maxconn {{ loadbalancer.global_connection_limit }}
{% endif %} {% endif %}
{% if ssl_cache is defined %}
tune.ssl.cachesize {{ ssl_cache }}
{% endif %}
{%- if cpu_count is defined and cpu_count > 1 %} {%- if cpu_count is defined and cpu_count > 1 %}
nbthread {{ cpu_count - 1 }} nbthread {{ cpu_count - 1 }}
cpu-map auto:1/1-{{ cpu_count - 1 }} 1-{{ cpu_count - 1 }} cpu-map auto:1/1-{{ cpu_count - 1 }} 1-{{ cpu_count - 1 }}

View File

@ -0,0 +1,9 @@
---
other:
- |
When a HTTPS termination listener gets configured, Octavia will tweak the
HAProxy `tune.ssl.cachesize` setting to use about half of the available
memory (free + buffers + cached) on the amphora minus the memory needed
for network sockets based on the global max connections setting.
This allows to make better reuse of existing SSL sessions and
helps to lower the number of computationally expensive SSL handshakes.