Tuning Nginx for Maximum Performance

Worker_processes

Make sure you use the correct amount of worker_processes in your /etc/nginx/nginx.conf. This should be equal to the amount of CPU cores in the output of

cat /proc/cpuinfo | grep processor
root@server1:~# cat /proc/cpuinfo | grep processor
processor : 0
processor : 1
processor : 2
processor : 3
processor : 4
processor : 5
processor : 6
processor : 7
root@server1:~#

In this example, we have eight CPU cores, so we set

vi /etc/nginx/nginx.conf

[...]
worker_processes 8;
[...]

Keepalive_timeout, sendfile, tcp_nopush, tcp_nodelay

Set keepalive_timeout to a sensible value like two seconds. Enable sendfile, tcp_nopush, and tcp_nodelay:

vi /etc/nginx/nginx.conf

[...]
http {
[...]
 sendfile on;
 tcp_nopush on;
 tcp_nodelay on;
 keepalive_timeout 2;
 types_hash_max_size 2048;
 server_tokens off;
[...]
}
[...]

File Cache

Enable the nginx file cache:

vi /etc/nginx/nginx.conf

[...]
http {
[...]
 ##
 # File Cache Settings
 ##
open_file_cache max=5000 inactive=20s;
 open_file_cache_valid 30s;
 open_file_cache_min_uses 2;
 open_file_cache_errors on;
[...]
}
[...]

Enable Gzip Compression

You can read more about Gzip compression here: How To Save Traffic With nginx’s HttpGzipModule (Debian Squeeze)

vi /etc/nginx/nginx.conf

[...]
http {
[...]
 ##
 # Gzip Settings
 ##

 gzip on;
 gzip_static on;
 gzip_disable "msie6";
 gzip_http_version 1.1;
 gzip_vary on;
 gzip_comp_level 6;
 gzip_proxied any;
 gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
 gzip_buffers 16 8k;
[...]
}
[...]

Enable The SSL Session Cache

If you serve https web sites, you should enable the SSL session cache:

vi /etc/nginx/nginx.conf

[...]
http {
[...]
 ssl_session_cache shared:SSL:10m;
 ssl_session_timeout 10m;
 ssl_ciphers HIGH:!aNULL:!MD5;
 ssl_prefer_server_ciphers on;
[...]
}
[...]

Use The FastCGI Cache

If you have cacheable PHP content, you can use the nginx FastCGI cache to cache that content. In your nginx.conf, add a line similar to this one:

vi /etc/nginx/nginx.conf

[...]
http {
[...]
 fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=microcache:10m max_size=1000m inactive=60m;
[...]
}
[...]

The cache directory /var/cache/nginx must exist and be writable for nginx:

mkdir /var/cache/nginx
chown www-data:www-data /var/cache/nginx

(By using tmpfs, you can even place the directory directly in your server’s memory which provides another small speed advantage – take a look at this tutorial to learn more: Storing Files/Directories In Memory With tmpfs).

In your vhost configuration, add the following block to your location ~ \.php$ {} section (you can modify it depending on when content should be cached and when not):

[...]
 # Setup var defaults
 set $no_cache "";
 # If non GET/HEAD, don't cache & mark user as uncacheable for 1 second via cookie
 if ($request_method !~ ^(GET|HEAD)$) {
 set $no_cache "1";
 }
 # Drop no cache cookie if need be
 # (for some reason, add_header fails if included in prior if-block)
 if ($no_cache = "1") {
 add_header Set-Cookie "_mcnc=1; Max-Age=2; Path=/";
 add_header X-Microcachable "0";
 }
 # Bypass cache if no-cache cookie is set
 if ($http_cookie ~* "_mcnc") {
 set $no_cache "1";
 }
 # Bypass cache if flag is set
 fastcgi_no_cache $no_cache;
 fastcgi_cache_bypass $no_cache;
 fastcgi_cache microcache;
 fastcgi_cache_key $scheme$host$request_uri$request_method;
 fastcgi_cache_valid 200 301 302 10m;
 fastcgi_cache_use_stale updating error timeout invalid_header http_500;
 fastcgi_pass_header Set-Cookie;
 fastcgi_pass_header Cookie;
 fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
[...]

So the full location ~ \.php$ {} section could look as follows:

[...]
location ~ \.php$ {

# Setup var defaults
 set $no_cache "";
 # If non GET/HEAD, don't cache & mark user as uncacheable for 1 second via cookie
 if ($request_method !~ ^(GET|HEAD)$) {
 set $no_cache "1";
 }
 # Drop no cache cookie if need be
 # (for some reason, add_header fails if included in prior if-block)
 if ($no_cache = "1") {
 add_header Set-Cookie "_mcnc=1; Max-Age=2; Path=/";
 add_header X-Microcachable "0";
 }
 # Bypass cache if no-cache cookie is set
 if ($http_cookie ~* "_mcnc") {
 set $no_cache "1";
 }
 # Bypass cache if flag is set
 fastcgi_no_cache $no_cache;
 fastcgi_cache_bypass $no_cache;
 fastcgi_cache microcache;
 fastcgi_cache_key $scheme$host$request_uri$request_method;
 fastcgi_cache_valid 200 301 302 10m;
 fastcgi_cache_use_stale updating error timeout invalid_header http_500;
 fastcgi_pass_header Set-Cookie;
 fastcgi_pass_header Cookie;
 fastcgi_ignore_headers Cache-Control Expires Set-Cookie;

try_files $uri =404;
 include /etc/nginx/fastcgi_params;
 fastcgi_pass unix:/var/lib/php5-fpm/web1.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param PATH_INFO $fastcgi_script_name;
 fastcgi_intercept_errors on;
}
[...]

This would cache pages with the return codes 200, 301, and 302 for ten minutes.

Use FastCGI Buffers

In your vhost configuration, you can add the following lines to your location ~ \.php$ {} section:

[...]
 fastcgi_buffer_size 128k;
 fastcgi_buffers 256 16k;
 fastcgi_busy_buffers_size 256k;
 fastcgi_temp_file_write_size 256k;
 fastcgi_read_timeout 240;
[...]

The full location ~ \.php$ {} section could look as follows:

[...]
location ~ \.php$ {
 try_files $uri =404;
 include /etc/nginx/fastcgi_params;
 fastcgi_pass unix:/var/lib/php5-fpm/web1.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param PATH_INFO $fastcgi_script_name;
 fastcgi_intercept_errors on;
fastcgi_buffer_size 128k;
 fastcgi_buffers 256 16k;
 fastcgi_busy_buffers_size 256k;
 fastcgi_temp_file_write_size 256k;
 fastcgi_read_timeout 240;
}
[...]

Make Browsers Cache Static Files With The expires Directive

Files (like images, CSS, JS, etc.) that don’t change often can be cached by the visitor’s browser by using the expires directive (see http://wiki.nginx.org/HttpHeadersModule#expires):

[...]
 location ~* \.(jpg|jpeg|png|gif|ico)$ {
 expires 365d;
 }
[...]

Disable Logging For Static Files

Normally it doesn’t make much sense to log images or CSS files in the access log. To reduce disk I/O, we can disable logging for such files, e.g. as follows:

[...]
 location ~* \.(jpg|jpeg|png|gif|ico)$ {
 log_not_found off;
 access_log off;
 }
[...]

Tuning PHP-FPM- Use A PHP Opcode Cache Like Xcache Or APC

Make sure you have a PHP opcode cache such as Xcache or APC installed. On Debian/Ubuntu, Xcache can be installed as follows:

apt-get install php5-xcache

APC can be installed as follows:

apt-get install php-apc

Make sure you have just one installed (either Xcache or APC), not both. Reload PHP-FPM after the installation:

/etc/init.d/php5-fpm reload

Allocate Enough Memory To Xcache/APC

If you have lots of PHP scripts, you should probably raise the memory that is allocated to Xcache or APC. For Xcache, you can do this in /etc/php5/conf.d/xcache.ini:

vi /etc/php5/conf.d/xcache.ini

[...]
xcache.size = 512M
[...]

Likewise for APC:

vi /etc/php5/conf.d/apc.ini

[...]
apc.shm_size="512"
[...]

Reload PHP-FPM after your modification:

/etc/init.d/php5-fpm reload

PHP-FPM Emergency Settings

This is more of a reliability setting than a performance setting: PHP-FPM can restart itself if it stops working:

vi /etc/php5/fpm/php-fpm.conf

[...]
; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
emergency_restart_threshold = 10

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated. This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
emergency_restart_interval = 1m

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
process_control_timeout = 10s
[...]

For PHP >= 5.3.9: Use The ondemand Process Manager

If you use PHP >= 5.3.9, you can use the ondemand process manager in a PHP-FPM pool instead of static or dynamic, this will save you some RAM:

[...]
pm = ondemand
pm.max_children = 100
pm.process_idle_timeout = 5s
[...]

Use Unix Sockets Instead Of TCP Sockets

To reduce networking overhead, you should configure your pools to use Unix sockets instead of TCP:

[...]
;listen = 127.0.0.1:9000
listen = /var/lib/php5-fpm/www.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
[...]

If you change this, you must of course adjust the location ~ \.php$ {} section in your nginx vhost to use the socket (fastcgi_pass unix:/var/lib/php5-fpm/www.sock; instead of fastcgi_pass 127.0.0.1:9000;):

[...]
location ~ \.php$ {
 try_files $uri =404;
 include /etc/nginx/fastcgi_params;
 ##fastcgi_pass 127.0.0.1:9000;
 fastcgi_pass unix:/var/lib/php5-fpm/www.sock;
 fastcgi_index index.php;
 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
 fastcgi_param PATH_INFO $fastcgi_script_name;
 fastcgi_intercept_errors on;
}
[...]

Avoid 502 Bad Gateway Errors With Sockets On Busy Sites

If you use Unix sockets with PHP-FPM, you might encounter random 502 Bad Gateway errors with busy websites. To avoid this, we raise the max. number of allowed connections to a socket. Open /etc/sysctl.conf…

vi /etc/sysctl.conf ... and set:

[...]
net.core.somaxconn = 4096
[...]

Run

sysctl -p

afterwards for the change to take effect.

Optimize Your my.cnf

You should use scripts such as mysqltuner.pl or tuning-primer.sh (or both) to find out which settings you should adjust in your my.cnf file. One of the most important variables is query_cache_size, and, if you use InnoDB tables, innodb_buffer_pool_size.

Download Sample conf and utilities

Zip file contains mysqltuner.pl, tuning-primer.sh, nginx.conf and default sample file

Source: https://www.howtoforge.com/configuring-your-lemp-system-linux-nginx-mysql-php-fpm-for-maximum-performance 

Share

Leave a Reply