nginx configuration tuning

Notes on nginx performance. Pulled from many sources including: https://www.linode.com/docs/web-servers/nginx/configure-nginx-for-optimized-performance

Worker Modifications

The easiest thing to set in your configuration is the right number of workers and connections

Worker Processes

In /etc/nginx/nginx.conf, set worker_processes 1; if you have a lower traffic site where nginx, a database, and a web application all run on the same server.

If you have a higher traffic site or a dedicated instance for nginx, set one worker per CPU core: worker_processes auto;

If you’d like to set this manually, you can utilize grep ^processor /proc/cpuinfo | wc -l to find the number of processes that the server can handle and adjust accordingly.

Worker Connections

The option worker_connections sets the maximum number of connections that can be processed at one time by each worker process. By default, the worker connection limit is 512, but many systems can handle more.

The appropriate sizing can be discovered through testing, as it is variable based on the type of traffic nginx is handling. The system’s core limitations can also be find through using ulimit:

ulimit -n

It will output a number as a result: 65536

You can also set use epoll, a scalable I/O event notification mechanism to trigger on events and make sure that I/O is utilized to the best of its ability.

Lastly, you can utilize multi_accept in order for a worker to accept all new connections at one time.

1
2
3
4
5
events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}
# Maximum open file descriptors per process. Should be > (worker_connections * worker_processes)
worker_rlimit_nofile 32768;

HTTP and TCP Optimizations

Keep Alive

Keep alive allows for fewer reconnections from the browser. Remember to place these settings inside the http {} directive.

  • keepalive_timeout and keepalive_requests control the keep alive settings.

  • sendfile optimizes serving static files from the file system, like logos.

  • tcp_nodelay allows nginx to make TCP send multiple buffers as individual packets.

  • tcp_nopush optimizes the amount of data sent down the wire at once by activating the TCP_CORK option within the TCP stack. TCP_CORK blocks the data until the packet reaches the MSS, which is equal to the MTU minus the 40 or 60 bytes of the IP header.

1
2
3
4
5
keepalive_timeout 65;
keepalive_requests 100000;
sendfile on;
tcp_nopush on;
tcp_nodelay on;

Buffer Size

Making tweaks to the buffer size can be advantageous. If the buffer sizes are too low, then nginx will write to a temporary file. This will cause for excessive disk I/O. Remember to place these settings inside the http {} directive.

  • client_body_buffer_size handles the client buffer size. Most client buffers are coming from POST method form submissions. 128k is normally a good choice for this setting.

  • client_max_body_size sets the max body buffer size. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client. For reference, browsers cannot correctly display 413 errors. Setting size to 0 disables checking of client request body size.

  • client_header_buffer_size handles the client header size. 1k is usually a sane choice for this by default.

  • large_client_header_buffers shows the maximum number and size of buffers for large client headers. 4 headers with 4k buffers should be sufficient here.

  • output_buffers sets the number and size of the buffers used for reading a response from a disk. If possible, the transmission of client data will be postponed until nginx has at least the set size of bytes of data to send. The zero value disables postponing data transmission.

1
2
3
4
5
6
client_body_buffer_size    128k;
client_max_body_size        10m;
client_header_buffer_size    1k;
large_client_header_buffers 4 4k;
output_buffers             2 32k;
postpone_output             1460;

Timeouts

Timeouts can also drastically improve performance. Remember to place these settings inside the http {} directive.

  • client_body_timeout sends directives for the time a server will wait for a body to be sent.

  • client_header_timeout sends directives for the time a server will wait for a header body to be sent. These directives are responsible for the time a server will wait for a client body or client header to be sent after request. If neither a body or header is sent, the server will issue a 408 error or Request time out.

  • send_timeout specifies the response timeout to the client. This timeout does not apply to the entire transfer but, rather, only between two subsequent client-read operations. Thus, if the client has not read any data for this amount of time, then nginx shuts down the connection.

1
2
3
4
reset_timedout_connection on;
client_header_timeout    60s;
client_body_timeout      15s;
send_timeout             10s;

Static Asset Serving

If your site serves static assets (such as CSS/JavaScript/images), nginx can cache these files for a short period of time. Adding this within your configuration block tells nginx to cache 1000 files for 30 seconds, excluding any files that haven’t been accessed in 20 seconds, and only files that have been accessed at least 5 times in that timeframe. If you aren’t deploying frequently you can safely bump up these numbers higher. Remember to place these settings inside the http {} directive.

#also see: https://easyengine.io/tutorials/nginx/open-file-cache/

1
2
3
4
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 5;
open_file_cache_errors off;

You can also cache via a particular location. Caching files for a long time is beneficial, especially if the files have a version control system delivered by the build process or CMS. This should be placed in the virtual host configuration or main configuration (e.g: /etc/nginx/sites-available/default)

1
2
3
location ~* .(woff|eot|ttf|svg|mp4|webm|jpg|jpeg|png|gif|ico|css|js)$ {
    expires 365d;
}

Gzipping Content

For content that is plain text, nginx can use gzip compression to serve back these assets compressed to the client. Modern web browsers will accept gzip compression and this will shave bytes off of each request that comes in for plain text assets. The list below is a “safe” list of compressible content types; however, you only want to enable the content types that you are utilizing within your web application. Remember to place these settings inside the http {} directive.

1
2
3
gzip on;
gzip_min_length 1000;
gzip_types text/html application/x-javascript text/css application/javascript text/javascript text/plain text/xml application/json application/vnd.ms-fontobject application/x-font-opentype application/x-font-truetype application/x-font-ttf application/xml font/eot font/opentype font/otf image/svg+xml image/vnd.microsoft.icon;

For more see:

Leave a Reply