# Maximum number of concurrent requests to process concurrently
# in a single service process, or 0 for no limit.
- MaxConcurrentRequests: 64
+ MaxConcurrentRequests: 4
# Maximum number of incoming requests to hold in a priority
# queue waiting for one of the MaxConcurrentRequests slots to be
#
# If MaxQueuedRequests is 0, respond 503 immediately to
# additional requests while at the MaxConcurrentRequests limit.
- MaxQueuedRequests: 64
+ MaxQueuedRequests: 128
# Maximum time a "lock container" request is allowed to wait in
# the incoming request queue before returning 503.
# Number of times a container can be unlocked before being
# automatically cancelled.
- MaxDispatchAttempts: 5
+ MaxDispatchAttempts: 10
# Default value for container_count_max for container requests. This is the
# number of times Arvados will create a new container to satisfy a container
#
# SPDX-License-Identifier: AGPL-3.0
-{%- set max_reqs = "__CONTROLLER_MAX_CONCURRENT_REQUESTS__" %}
+{%- set max_workers = ("__CONTROLLER_MAX_WORKERS__" or grains['num_cpus'])|int %}
+{%- set max_reqs = ("__CONTROLLER_MAX_QUEUED_REQUESTS__" or 128)|int %}
# The variables commented out are the default values that the formula uses.
# The uncommented values are REQUIRED values. If you don't set them, running
Password: __INITIAL_USER_PASSWORD__
### API
- {%- if max_reqs != "" %}
API:
- MaxConcurrentRequests: {{ max_reqs|int }}
- {%- endif %}
+ MaxConcurrentRequests: {{ max_workers * 2 }}
+ MaxQueuedRequests: {{ max_reqs }}
### CONTAINERS
{%- set dispatcher_ssh_privkey = "__DISPATCHER_SSH_PRIVKEY__" %}
{%- set passenger_ruby = '/usr/local/rvm/wrappers/default/ruby'
if grains.osfinger in ('CentOS Linux-7', 'Ubuntu-18.04', 'Debian-10') else
'/usr/bin/ruby' %}
-{%- set max_reqs = "__CONTROLLER_MAX_CONCURRENT_REQUESTS__" %}
+{%- set max_workers = ("__CONTROLLER_MAX_WORKERS__" or grains['num_cpus'])|int %}
+{%- set max_reqs = ("__CONTROLLER_MAX_QUEUED_REQUESTS__" or 1024)|int %}
### NGINX
nginx:
### PASSENGER
passenger:
passenger_ruby: {{ passenger_ruby }}
- passenger_max_pool_size: {{ "__CONTROLLER_NGINX_WORKERS__" or grains['num_cpus'] }}
- {%- if max_reqs != "" %}
- # Default is 100 -- Configuring this a bit higher than API.MaxConcurrentRequests
- # to be able to handle /metrics requests even on heavy load situations.
- passenger_max_request_queue_size: {{ (max_reqs|int * 1.1)|round|int }}
- {%- endif %}
+ passenger_max_pool_size: {{ max_workers }}
+
+ # Make the passenger queue small (twice the concurrency, so
+ # there's at most one pending request for each busy worker)
+ # because controller reorders requests based on priority, and
+ # won't send more than API.MaxConcurrentRequests to passenger
+ # (which is max_workers * 2), so things that are moved to the head
+ # of the line get processed quickly.
+ passenger_max_request_queue_size: {{ max_workers * 2 + 1 }}
### SERVER
server:
# include: 'modules-enabled/*.conf'
load_module: {{ passenger_mod }}
{% endif %}
- worker_processes: {{ "__CONTROLLER_NGINX_WORKERS__" or grains['num_cpus'] }}
- {%- if max_reqs != "" %}
- worker_rlimit_nofile: {{ (max_reqs|int * 3)|round|int }}
- events:
- worker_connections: {{ (max_reqs|int * 3)|round|int }}
- {%- else %}
- worker_rlimit_nofile: 4096
+ worker_processes: {{ max_workers }}
+
+ # each request is up to 3 connections (1 with client, 1 proxy to
+ # controller, then potentially 1 from controller back to
+ # passenger). Each connection consumes a file descriptor.
+ # That's how we get these calculations
+ worker_rlimit_nofile: {{ max_reqs * 3 + 1 }}
events:
- worker_connections: 1024
- {%- endif %}
+ worker_connections: {{ max_reqs * 3 + 1 }}
### SNIPPETS
snippets:
DISABLED_CONTROLLER=""
# Performance tuning parameters
-#CONTROLLER_NGINX_WORKERS=
-CONTROLLER_MAX_CONCURRENT_REQUESTS=64
+#CONTROLLER_MAX_WORKERS=
+#CONTROLLER_MAX_QUEUED_REQUESTS=
# The directory to check for the config files (pillars, states) you want to use.
# There are a few examples under 'config_examples'.
s#__SSL_KEY_ENCRYPTED__#${SSL_KEY_ENCRYPTED}#g;
s#__SSL_KEY_AWS_REGION__#${SSL_KEY_AWS_REGION}#g;
s#__SSL_KEY_AWS_SECRET_NAME__#${SSL_KEY_AWS_SECRET_NAME}#g;
- s#__CONTROLLER_NGINX_WORKERS__#${CONTROLLER_NGINX_WORKERS:-}#g;
- s#__CONTROLLER_MAX_CONCURRENT_REQUESTS__#${CONTROLLER_MAX_CONCURRENT_REQUESTS:-64}#g;
+ s#__CONTROLLER_MAX_WORKERS__#${CONTROLLER_MAX_WORKERS:-}#g;
+ s#__CONTROLLER_MAX_QUEUED_REQUESTS__#${CONTROLLER_MAX_QUEUED_REQUESTS:-128}#g;
s#__MONITORING_USERNAME__#${MONITORING_USERNAME}#g;
s#__MONITORING_EMAIL__#${MONITORING_EMAIL}#g;
s#__MONITORING_PASSWORD__#${MONITORING_PASSWORD}#g;