GIT – nginx  is a small and fast webserver which generally outperforms most of the alternatives out of the box, however there is always room for improvement.

In addition to operating as a web- can also be used as reverse HTTP , forwarding requests it recieves to different back-end servers.

General Tuning

nginx uses a fixed number of workers, each of which handles incoming requests. The general rule of thumb is that you should have one worker for each CPU-core your server contains.

You can count the CPUs available to your system by running:

$ grep ^processor /proc/cpuinfo | wc -l

With a quad-core processor this would give you a configuration that started like so:

# One worker per CPU-core.
worker_processes  4;

events {
    worker_connections  8096;
    multi_accept        on;
    use                 epoll;
}

worker_rlimit_nofile 40000;

http {
    sendfile           on;
    tcp_nopush         on;
    tcp_nodelay        on;
    keepalive_timeout  15;

    # Your content here ..
}

Here we’ve also raised the worker_connections setting, which specifies how many connections each worker process can handle.

The maximum number of connections your server can process is the result of:

  • worker_processes * worker_connections (= 32384 in our example).

We’ve enabled multi_accept which causes nginx to attempt to immediately accept as many connections as it can, subject to the socket setup.

Finally use of the epoll event-model is generally recommended for best throughput.

Timeouts

Timeouts can also drastically improve performance.

The client_body_timeout and client_header_timeout 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.

The keepalive_timeout assigns the timeout for keep-alive connections with the client. Simply put, Nginx will close connections with the client after this period of time.

Finally, the send_timeout is established not on the entire transfer of answer, but only between two operations of reading; if after this time client will take nothing, then Nginx is shutting down the connection.

client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;

Compression

One of the first things that many people try to do is to enable the gzip compression module available with nginx. The intention here is that the objects which the server sends to requesting clients will be smaller, and thus faster to send.

However this involves the trade-off common to tuning, performing the compression takes CPU resources from your server, which frequently means that you’d be better off not enabling it at all.

Generally the best approach with compression is to only enable it for large files, and to avoid compressing things that are unlikely to be reduced in size (such as images, executables, and similar binary files).

With that in mind the following is a sensible configuration:

gzip  on;
gzip_vary on;
gzip_min_length 10240;
gzip_proxied expired no- no-store private auth;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
gzip_disable "MSIE [1-6]\.";

This enables compression for files that are over 10k, aren’t being requested by early versions of Microsoft’s Internet Explorer, and only attempts to compress text-based files.

Worker Processes and Worker Connections

The first two variables we need to tune are the worker processes and worker connections. Before we jump into each setting, we need to understand what each of these directives control. The worker_processes directive is the sturdy spine of life for Nginx. This directive is responsible for letting our virtual server know many workers to spawn once it has become bound to the proper and port(s). It is common practice to run 1 worker process per core. Anything above this won’t hurt your system, but it will leave idle processes usually just lying about.

To figure out what number you’ll need to set worker_processes to, simply take a look at the amount of cores you have on your setup. If you’re using the DigitalOcean 512MB setup, then it’ll probably be one core. If you end up fast resizing to a larger setup, then you’ll need to check your cores again and adjust this number accordingly. We can accomplish this by greping out the cpuinfo:

grep processor /proc/cpuinfo | wc -l

Let’s say this returns a value of 1. Then that is the amount of cores on our machine!

The worker_connections tells our worker processes how many people can simultaneously be served by Nginx. The default value is 768; however, considering that every browser usually opens up at least 2 connections/server, this number can half. This is why we need to adjust our worker connections to its full potential. We can check our core’s limitations by issuing a ulimit :

ulimit -n

On a smaller machine (512MB droplet) this number will probably read 1024, which is a good starting number.

Let’s update our config:

sudo nano /etc/nginx/nginx.conf

worker_processes 1;
worker_connections 1024;

Remember, the amount of clients that can be served can be multiplied by the amount of cores. In this case, we can server 1024 clients/second. This is, however, even further mitigated by the keepalive_timeout directive.

Buffers

Another incredibly important tweak we can make is to the buffer size. If the buffer sizes are too low, then Nginx will have to write to a temporary file causing the to read and write constantly. There are a few directives we’ll need to understand before making any decisions.

client_body_buffer_size: This handles the client buffer size, meaning any POST actions sent to Nginx. POST actions are typically form submissions.

client_header_buffer_size: Similar to the previous directive, only instead it handles the client header size. For all intents and purposes, 1K is usually a decent size for this directive.

client_max_body_size: The maximum allowed size for a client request. If the maximum size is exceeded, then Nginx will spit out a 413 error or Request Entity Too Large.

large_client_header_buffers: The maximum number and size of buffers for large client headers.

client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;

Client Caching

A simple way of avoiding your server handling requests is if remote clients believe their content is already up-to-date.

To do this you want to set suitable cache-friendly headers, and a simple way of doing that is to declare that all images, etc, are fixed for a given period of time:

     location ~* \.(jpg|jpeg|gif|png|css|js|ico|xml)$ {
         access_log        off;
         log_not_found     off;
         expires           30d;
     }

Here we’ve disabled logging of media-files, and configured several suffixes which will be considered valid (and thus not re-fetched) for 30 days. You might want to adjust the period if you’re editing your CSS files frequently.

Filehandle Cache

If you’re serving a large number of static files you’ll benefit from keeping filehandles to requested files open – this avoids the need to reopen them in the future.

NOTE: You should only run with this enabled if you’re not editing the files at the time you’re serving them. Because file accesses are cached any 404s will be cached too, similarly file-sizes will be cached, and if you change them your served content will be out of date.

The following is a good example, which can be placed in either the server section of your nginx config, or within the main http block:

open_file_cache          max=2000 inactive=20s;
open_file_cache_valid    60s;
open_file_cache_min_uses 5;
open_file_cache_errors   off;

This configuration block tells the server to cache 2000 open filehandles, closing handles that have no hits for 20 seconds. The cached handles are considered valid for 60 seconds, and only files that were accessed five times will be considered suitable for caching.

The net result should be that frequently accessed files have handles cached for them, which will cut down on filesystem accesses.

Tip: You might consider the kernel tuning section, which discusses raising the file-handle limit.

Logging

Nginx logs every request that hits the VPS to a log file. If you use analytics to this, you may want to turn this functionality off. Simply edit the access_log directive:

access_log off;

Tuning for

Many sites involve the use of PHP, for example any site built around wordpress .

As there is no native mod_php for nginx the recommended way to run PHP applications involves the use of PHP-FPM . To use PHP-FPM you essentially proxy requests for PHP files as follows:

        # execute all .php files via php-fpm
        location ~ .php$ {
            # connect to a unix domain-socket:
            fastcgi_pass   unix:/var/run/php5-fpm.sock;
            fastcgi_index  index.php;

            fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;

            fastcgi_buffer_size 128k;
            fastcgi_buffers 256 16k;
            fastcgi_busy_buffers_size 256k;
            fastcgi_temp_file_write_size 256k;

            # This file is present on  systems..
            include fastcgi_params;
        }

Notice that this uses a Unix domain-socket to connect to FPM, so you need to ensure that you change /etc/php5/fpm/pool.d/www.conf to read:

listen = /var/run/php5-fpm.sock

This ensures that FPM will listen on a domain socket, rather than the default of listening on a network-socket (the default is “listen=127.0.0.1:9000“).

By default PHP-FPM will start a number of dedicated workers, each running an instance of PHP. If you’re not swamped for memory you can increase the number of workers to increase concurrent-throughput.

Edit the file /etc/php5/fpm/pool.d/www.conf to change the number of children:

; set a fixed number of php workers
pm = static

; start up 12 php processes
pm.max_children = 12

This is an example setting, of the kind we mention in the considerations section – the value of 12 is just an example, which you will need to test under-load to see if it is reasonable for your particular setup.

Finally you can configure PHP-FPM to restart automatically, if there are problems. In this example we restart if ten child processes die within 1 minute, and we allow 10 seconds to pass before that happens.

This is a global configuration and belongs in /etc/php5/fpm/php-fpm.conf:

emergency_restart_threshold 10
emergency_restart_interval 1m
process_control_timeout 10s

TIP: You might consider the use of the x-cache, which will cache parsed versions of your PHP-files. This should provide a speedup, even in a PHP-FPM setup.

Print Friendly

Comments

comments

Bài viết liên quan