KML_FLASHEMBED_PROCESS_SCRIPT_CALLS
 

Speeding Things Up in the Cloud with NGINX

March 26th, 2012 by - 10,361 views

clip_image001 clip_image002 clip_image004

It’s been no secret to us in the high-performance, web server in-crowd that NGINX (pronounced “engine-x”) has been taking the webhosting world by storm for the last several years; *sites like WordPress, Facebook, Hulu, Github, SourceForge and more have been offloading some or many functions onto NGINX. I had originally been exposed to NGINX whilst researching for a higher-performance web server that was 64-bit friendlier than Apache, and that was did not use single threads. Apache has an enormous memory footprint on 64-bit systems and is a single-threaded application.

NGINX is a very flexible HTTP server that can also serve as a reverse proxy, load balancer, caching server, and an IMAP/POP3 proxy. Unlike Apache, however, the configuration is a little bit more involved and can be a big change for Apache loyalists.

In this is example, NGINX will be configured as a full webserver with PHP support. My goal when conjuring this project was to make a pre-configured Community GSI on the GoGrid Exchange with as little modification as possible to ensure a “pure” environment. If you’re anything like me, you might tremble at the thought of even using a typical, pre-configured server with a LAMP stack; I personally like setting things up from scratch, but there’ve been plenty of situations where I would’ve preferred a pre-configured solution. Hopefully I can capture the essence of my intentions.

One thing I should note before I get started is that NGINX does not have a module for PHP the way Apache does; PHP must be run using the FastCGI methodology. Much like the way you would pass requests to a Java container or reverse proxy, so must we for PHP.

The first thing I should mention is that I’m using the EPEL and IUS repositories to for the latest versions of NGINX and PHP-FPM. IUS is the official repository for RHEL/CentOS as referenced by PHP.net. Using these 2 repositories will not alter any existing packages on your system.

I added the repositories by installing their RPM’s.

[root@00581-1-1042302 ~] # rpm -Uvh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
Retrieving http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm
Preparing... ########################################### [100%]
[root@00581-1-1042302 ~] # rpm –Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm
Retrieving http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm
Preparing... ########################################### [100%]
# ls /etc/yum.repos.d/
CentOS-Base.repo epel.repo ius-dev.repo
CentOS-Debuginfo.repo epel-testing.repo ius.repo
CentOS-Media.repo ius-archive.repo ius-testing.repo

(Note: for CentOS-Base.repo “epel.repo”, is enabled by default & “ius-dev.repo” is disabled by default; for CentOS-Debuginfo.repo, “epel-testing.repo” is disabled by default & ius.repo is enabled by default; for CentOS-Media.repo, both “ius-archive.repo” & “ius-testing.repo” are disabled by default.)

Now let’s examine the /etc/nginx/nginx.conf configuration file. I’ve purposefully only included the changes that I made which are mostly based around commonsense performance and a Debian-like folder structure for easily enabling and disabling active sites.

Any change that I’ve made in PHP-FPM or NGINX has “GoGrid” appended to the line, as indicated by my grep below.

[root@00581-1-1042302 ~]# grep GoGrid /etc/nginx/nginx.conf
worker_processes 1; #GoGrid - Change to number of CPU threads/cores.
keepalive_timeout 5; #GoGrid
gzip on; #GoGrid
gzip_proxied any; #GoGrid
gzip_comp_level 1; #GoGrid
gzip_buffers 16 8k; #GoGrid
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript; #GoGrid
include /etc/nginx/sites-enabled/*; #GoGrid

worker_processes – The number of nginx processes that will run at one time. This should be equal to the amount of CPU cores your server has. Note that each process can handle potentially handle thousands of worker_connections.

worker_connections – Each worker is setup to handle 1024 connections (although not seen above).

gzip_on – gzip is commonly turned on to decrease throughput and speed up transaction times.

Include /etc/nginx/sites/enabled*; – Debian-style folder structure where one creates a symlink from sites-enables to the real config file in sites-available.

[root@00581-1-1042302 ~]# ls -l /etc/nginx/sites-enabled/example.com

lrwxrwxrwx 1 root root 30 Mar 16 03:44 /etc/nginx/sites-enabled/example.com -> ../sites-available/example.com

Now that we’ve covered the NGINX configuration file, let’s take a look at the /etc/nginx/fastcgi_params file. This file is supposed to be shared between all website configuration files to provide a common environment. Rarely have I needed to modify anything in this file besides what is mentioned below. Again, I’m only including what I’ve changed or added.

#GoGrid - The following line is commented out to avoid duplicate filenames in the URI with most common configurations. #fastcgi_param SCRIPT_FILENAME $request_filename; #GoGrid #GoGrid - Commonly Added Options #fastcgi_connect_timeout 30; #fastcgi_send_timeout 30; #fastcgi_read_timeout 30; #fastcgi_buffer_size 128k; #fastcgi_buffers 4 256k; #fastcgi_busy_buffers_size 256k; #fastcgi_temp_file_write_size 256k; #fastcgi_intercept_errors on;

fastcgi_param – Since this is already defined in most individual website configurations (with the corresponding full path to the document root) on nginx, I comment this out, as it can lead to duplicate php URI’s, like www.example.com/phpinfo.php/phpinfo.php

GoGrid – Commonly Added Options – These are performance options that many examples are modeled after. You can find these settings in blogs and nginx sample config files alike. In particular, setting the timeouts is important to sever realistically, timed-out connections. I would recommend un-commenting these out and using them, but I left them disabled in order to stick to my simplicity theme.

The individual website configuration in a vhost-style file/directory is incredibly standard. We’ve got logging, server_name, document root, directory index, etc. Anyone who’s worked with webservers should be relatively comfortable.

server {
listen XXX.XXX.XXX.XXX:80 backlog=1024;
server_name www.example.com;
autoindex off;
access_log /var/www/vhosts/example.com/log/nginx_access.log;
error_log /var/www/vhosts/example.com/log/nginx_error.log;

location / {
root /var/www/vhosts/example.com/html;
index index.php index.html;
}

location ~ \.php$ {
fastcgi_pass unix:/tmp/php-fpm.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/vhosts/example.com/html$fastcgi_script_name; # same path as above
include fastcgi_params;
}
}

#server {
# listen XXX.XXX.XXX.XXX:443 ssl;
# ssl_certificate /usr/local/certs/www.example.com.nginx.pem;
# ssl_certificate_key /usr/local/certs/www.example.com.nginx.key;
# server_name www.example.com;
# autoindex off;
# access_log off;
# error_log /var/www/vhosts/example.com/log/nginx_ssl_error.log;
#
# location / {
# root /var/www/vhosts/example.com/html;
#index index.php index.html;
#
#}
#
#location ~ \.php$ {
# fastcgi_pass unix:/tmp/php-fpm.socket;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /var/www/vhosts/example.com/html$fastcgi_script_name; # same path as above
# include fastcgi_params;
#}
#}

Last, but not least, is the www.conf pool file in /etc/php-fpm.d/ folder. NGINX and PHP-FPM have their own performance settings, which can be a bit change of pace from straight Apache and mod_php.

As usual, only the changed I’ve made have been shown below.

[root@00581-1-1042302 ~]# grep GoGrid www.conf
listen = /tmp/php-fpm.socket; GoGrid
user = www-data; GoGrid
group = www-data; GoGrid
pm.max_children = 500; GoGrid
pm.start_servers = 50; GoGrid
pm.min_spare_servers = 50; GoGrid
pm.max_spare_servers = 350; GoGrid
pm.max_requests = 500; GoGrid
; slowlog = /var/log/php-fpm/www-slow.log; GoGrid

listen – I always change the listen address from a TCP socket to a unix socket. For me this is just about having a clean netstat reading. Most Sys Admins likely keep this on a TCP for a myriad of reasons. To switch this back to a TCP socket, go into the config file and uncomment the line directly above it and comment this setting out. Don’t forget to update the fastcgi_pass option in the website configuration file.

user/group – User www-data created with a homedir of /var/www to segregate nginx and Apache users.

pm.setting – Common settings similar to Apache’s. See here for more information.

slowlog – Turned off, as this is more of a debugging feature.

Although we’ve gone over a lot of details about the NGINX and PHP-FPM setup, the nice thing about this image is that it’s immediately ready to use without any modification!

Simply add a server through the GoGrid portal and search for nginx in the search bar.

addserver

nginxsearch

After you’ve deployed this MyGSI image, simply edit your website configuration file with your server’s IP, and put the IP address of the server in the browser and you should be greeted with a php info page. The firewall and update-rc.d profiles are already set up.

Now get out there, experiment, and let me know how it goes!

Leave a reply