This document summarizes the setup and performance of Nginx 0.8.x with PHP 5.2.13 using the FastCGI protocol on Linux. It finds that Nginx can handle over 30,000 concurrent connections using less than 2GB of RAM, while Apache struggled to handle 3,000 connections using over 3GB of RAM. Tests show Nginx serving PHP content is about twice as fast as Apache under load. The document provides installation instructions for compiling and configuring Nginx, PHP, and other supporting libraries on CentOS or RedHat Linux.
Streamlining Python Development: A Guide to a Modern Project Setup
Nginx 0.8.x + php 5.2.13 (fast cgi) setup web server
1. Nginx 0.8.x + PHP 5.2.13 (FastCGI) setup Web server
nginx [engine x] is a HTTP and reverse proxy server, as well as a mail proxy server written by Igor
Sysoev. It has been running for more than five years on many heavily loaded Russian sites
includingRambler (RamblerMedia.com). According to Netcraft nginx served or proxied 4.70% busiest
sites in April 2010. Here are some of success stories: FastMail.FM, WordPress.com.
In the case of highly concurrent connections, Nginx Apache server is a good substitute. Nginx also can
serve as a layer 7 load balancing server to use. According to my test results, Nginx 0.8.46 + PHP 5.2.14
(FastCGI) can withstand more than 30,000 concurrent connections, equivalent to Apache under the
same 10 times.
In my experience, 4GB of RAM + Apache (prefork model) generally can only handle 3,000 concurrent
connections, as they will occupy more than 3GB of memory, have to 1GB of memory reserved for the
system. I have had two Apache servers, as set in the configuration file MaxClients to 4000, when the
number of concurrent connections to Apache during 3800, resulting in server memory and Swap space
with full collapse.
This station Nginx 0.8.46 + PHP 5.2.14 (FastCGI) server 30 000 concurrent connections, the opening 10
Nginx process consumes 150M of memory (15M * 10 = 150M), open 64 php-cgi process consumes
1280M memory (20M * 64 = 1280M), plus the memory consumed by the system itself, a total
consumption of less than 2GB of memory. If the server memory is smaller, can only open 25 php-cgi
process php-cgi so the total amount of memory consumed only 500M.
In the 30,000 concurrent connections, the access to Nginx 0.8.46 + PHP 5.2.14 (FastCGI) PHP server
process is still fast. The figure below shows the status of Nginx monitoring page shows the number of
active connections for the 28457 (on the monitoring page Nginx configuration, will be given in this
article continues the Nginx configuration file specify):
I have two production environment Nginx + PHP5 (FastCGI) server, running more than a pure PHP
general complex dynamic process, a single Nginx + PHP5 (FastCGI) server running PHP dynamic is
capable of more than “700 r/s “can take 60 million per day (700 * 60 * 60 * 24 = 60.48 million) of visits,
the server’s system load is not high:
2. The following is 100 concurrent connections to the pressure were the same production environment
under load balancer to provide the same service on two servers, one for the Nginx, another for the
Apache, Nginx number of requests per second is twice the Apache more, Nginx server system load,
CPU usage much lower than the Apache:
You can open connections to 10,000 ~ 30,000, to pressure Nginx and Apache on the phpinfo.php, it is
browser access Nginx on phpinfo.php all normal, and access to Apache server phpinfo.php, is the page
can not be displayed. 4G of RAM, even if re-optimization, Apache and making it difficult “webbench-c
30000-t 60 http://xxx.xxx.xxx.xxx/phpinfo.php” under the pressure of the normal access, and adjust the
parameters optimized The Nginx can.
Note: webbench do stress testing, the software itself will consume CPU and memory resources, in order
to test accuracy, please webbench installed on another server.
The results :##### Nginx + PHP #####
[root@localhost webbench-1.5]# webbench -c 100 -t 30 http://192.168.1.21/phpinfo.php
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://192.168.1.21/phpinfo.php
100 clients, running 30 sec.
Speed=102450 pages/min, 16490596 bytes/sec.
Requests: 51225 susceed, 0 failed.
top – 14:06:13 up 27 days, 2:25, 2 users, load average: 14.57, 9.89, 6.51
Tasks: 287 total, 4 running, 283 sleeping, 0 stopped, 0 zombie
Cpu(s): 49.9% us, 6.7% sy, 0.0% ni, 41.4% id, 1.1% wa, 0.1% hi, 0.8% si
Mem: 6230016k total, 2959468k used, 3270548k free, 635992k buffers
Swap: 2031608k total, 3696k used, 2027912k free, 1231444k cached
The results :##### Apache + PHP #####
[root@localhost webbench-1.5]# webbench -c 100 -t 30 http://192.168.1.27/phpinfo.php
Webbench – Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://192.168.1.27/phpinfo.php
100 clients, running 30 sec.
Speed=42184 pages/min, 31512914 bytes/sec.
Requests: 21092 susceed, 0 failed.
top – 14:06:20 up 27 days, 2:13, 2 users, load average: 62.15, 26.36, 13.42
Tasks: 318 total, 7 running, 310 sleeping, 0 stopped, 1 zombie
Cpu(s): 80.4% us, 10.6% sy, 0.0% ni, 7.9% id, 0.1% wa, 0.1% hi, 0.9% si
Mem: 6230016k total, 3075948k used, 3154068k free, 379896k buffers
Swap: 2031608k total, 12592k used, 2019016k free, 1117868k cached
Why Nginx’s performance is much higher than Apache? Thanks to Nginx to use the latest epoll (Linux
2.6 kernel) and kqueue (freebsd) network I/O model, but Apache is using a traditional select models.
3. Currently under Linux can withstand high concurrent access of the Squid, Memcached have adopted
the epoll network I/O model.
Installation steps:
(System requirements: Linux 2.6 + kernel, the Linux operating system in this article CentOS 5.3, RedHat
AS4 on the other also in the successful installation)
First, access to relevant open source:
1 .【 CentOS Linux】 CentOS Linux system using yum command that comes with the installation,
upgrade the required libraries (RedHat and other Linux distributions can be found from the
installation CD in the library of the RPM package to install):
sudo -s
LANG=C
yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel
libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel bzip2 bzip2-devel ncurses
ncurses-devel curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel libidn libidn-devel openssl
openssl-devel openldap openldap-devel nss_ldap openldap-clients openldap-servers
2, RedHat Linux】 RedHat and other Linux distributions can be found from the installation CD in
【
the library of the RPM package (prior to a similar “rpm-qa | grep libjpeg” the command to see
whether there needed to RPM package, usually ” xxx-devel “does not exist, need to install).
RedHat can use the RPM package to install CentOS
(1) RPM Package
http://rpm.pbone.net/
http://www.rpmfind.net/
(2) RedHat AS4 system environment, usually lack the support package is installed:
a. i386
libjpeg-devel-6b-33.i386.rpm
freetype-devel-2.1.9-1.i386.rpm
libpng-devel-1.2.7-1.i386.rpm
b. x86_64
libjpeg-devel-6b-33.x86_64.rpm
freetype-devel-2.1.9-1.x86_64.rpm
libpng-devel-1.2.7-1.x86_64.rpm
3, Download source code package:
mkdir -p /data0/software
cd /data0/software
wget http://sysoev.ru/nginx/nginx-0.8.46.tar.gz
wget http://www.php.net/get/php-5.2.14.tar.gz/from/this/mirror
wget http://php-fpm.org/downloads/php-5.2.14-fpm-0.5.14.diff.gz
wget http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.3-m3.tar.gz/from/http://mysql.he.net/
wget http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.13.1.tar.gz
4. wget http://downloads.sourceforge.net/mcrypt/libmcrypt-2.5.8.tar.gz?
modtime=1171868460&big_mirror=0
wget http://downloads.sourceforge.net/mcrypt/mcrypt-2.6.8.tar.gz?modtime=1194463373&big_mirror=0
wget http://pecl.php.net/get/memcache-2.2.5.tgz
wget http://downloads.sourceforge.net/mhash/mhash-0.9.9.9.tar.gz?
modtime=1175740843&big_mirror=0
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.10.tar.gz
wget http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2
wget http://pecl.php.net/get/PDO_MYSQL-1.0.2.tgz
wget http://blog.s135.com/soft/linux/nginx_php/imagick/ImageMagick.tar.gz
wget http://pecl.php.net/get/imagick-2.3.0.tgz
Second, install PHP 5.2.14 (FastCGI mode)
1, build the support needed to install PHP 5.2.14 package:
tar zxvf libiconv-1.13.1.tar.gz
cd libiconv-1.13.1/
./configure –prefix=/usr/local
make
make install
cd ../
tar zxvf libmcrypt-2.5.8.tar.gz
cd libmcrypt-2.5.8/
./configure
make
make install
/sbin/ldconfig
cd libltdl/
./configure –enable-ltdl-install
make
make install
cd ../../
tar zxvf mhash-0.9.9.9.tar.gz
cd mhash-0.9.9.9/
./configure
make
make install
cd ../
ln -s /usr/local/lib/libmcrypt.la /usr/lib/libmcrypt.la
ln -s /usr/local/lib/libmcrypt.so /usr/lib/libmcrypt.so
ln -s /usr/local/lib/libmcrypt.so.4 /usr/lib/libmcrypt.so.4
ln -s /usr/local/lib/libmcrypt.so.4.4.8 /usr/lib/libmcrypt.so.4.4.8
ln -s /usr/local/lib/libmhash.a /usr/lib/libmhash.a
5. ln -s /usr/local/lib/libmhash.la /usr/lib/libmhash.la
ln -s /usr/local/lib/libmhash.so /usr/lib/libmhash.so
ln -s /usr/local/lib/libmhash.so.2 /usr/lib/libmhash.so.2
ln -s /usr/local/lib/libmhash.so.2.0.1 /usr/lib/libmhash.so.2.0.1
ln -s /usr/local/bin/libmcrypt-config /usr/bin/libmcrypt-config
tar zxvf mcrypt-2.6.8.tar.gz
cd mcrypt-2.6.8/
/sbin/ldconfig
./configure
make
make install
cd ../
2, compile install MySQL 5.5.3-m3
/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql mysql
tar zxvf mysql-5.5.3-m3.tar.gz
cd mysql-5.5.3-m3/
./configure –prefix=/usr/local/webserver/mysql/ –enable-assembler –with-extra-charsets=complex –
enable-thread-safe-client –with-big-tables –with-readline –with-ssl –with-embedded-server –enable-
local-infile –with-plugins=partition,innobase,myisammrg
make && make install
chmod +w /usr/local/webserver/mysql
chown -R mysql:mysql /usr/local/webserver/mysql
cd ../
Note: The following additional steps, if you would like to run the MySQL database server, perform the
following steps. If you just want to make PHP support for MySQL, be able to connect to other servers on
the MySQL database, then the following two steps need to perform
A, create a MySQL database storage directory:
mkdir -p /data0/mysql/3306/data/
mkdir -p /data0/mysql/3306/binlog/
mkdir -p /data0/mysql/3306/relaylog/
chown -R mysql:mysql /data0/mysql/
B,Establish a data table:
/usr/local/webserver/mysql/bin/mysql_install_db –basedir=/usr/local/webserver/mysql –
datadir=/data0/mysql/3306/data –user=mysql
C,Create my.cnf configuration file
vi /data0/mysql/3306/my.cnf
Enter the following:
9. G,MySQL command line log management server (direct carriage return when prompted for a
password):
/usr/local/webserver/mysql/bin/mysql -u root -p -S /tmp/mysql.sock
H,Enter the following SQL statement, create a user with root privileges (admin) and password
(12345678):
GRANT ALL PRIVILEGES ON *.* TO ‘admin’@'localhost’ IDENTIFIED BY ’12345678′;
GRANT ALL PRIVILEGES ON *.* TO ‘admin’@’127.0.0.1′ IDENTIFIED BY ’12345678′;
3, compiler installed PHP (FastCGI)
tar zxvf php-5.2.14.tar.gz
gzip -cd php-5.2.14-fpm-0.5.14.diff.gz | patch -d php-5.2.14 -p1
cd php-5.2.14/
./configure –prefix=/usr/local/webserver/php –with-config-file-path=/usr/local/webserver/php/etc –with-
mysql=/usr/local/webserver/mysql –with-mysqli=/usr/local/webserver/mysql/bin/mysql_config –with-
iconv-dir=/usr/local –with-freetype-dir –with-jpeg-dir –with-png-dir –with-zlib –with-libxml-dir=/usr –
enable-xml –disable-rpath –enable-discard-path –enable-safe-mode –enable-bcmath –enable-shmop –
enable-sysvsem –enable-inline-optimization –with-curl –with-curlwrappers –enable-mbregex –enable-
fastcgi –enable-fpm –enable-force-cgi-redirect –enable-mbstring –with-mcrypt –with-gd –enable-gd-
native-ttf –with-openssl –with-mhash –enable-pcntl –enable-sockets –with-ldap –with-ldap-sasl –with-
xmlrpc –enable-zip –enable-soap
make ZEND_EXTRA_LIBS=’-liconv’
make install
cp php.ini-dist /usr/local/webserver/php/etc/php.ini
cd ../
4, compile install PHP5 Extension Module
tar zxvf memcache-2.2.5.tgz
cd memcache-2.2.5/
/usr/local/webserver/php/bin/phpize
./configure –with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
cd ../
tar jxvf eaccelerator-0.9.6.1.tar.bz2
cd eaccelerator-0.9.6.1/
/usr/local/webserver/php/bin/phpize
./configure –enable-eaccelerator=shared –with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
cd ../
10. tar zxvf PDO_MYSQL-1.0.2.tgz
cd PDO_MYSQL-1.0.2/
/usr/local/webserver/php/bin/phpize
./configure –with-php-config=/usr/local/webserver/php/bin/php-config –with-pdo-
mysql=/usr/local/webserver/mysql
make
make install
cd ../
tar zxvf ImageMagick.tar.gz
cd ImageMagick-6.5.1-2/
./configure
make
make install
cd ../
tar zxvf imagick-2.3.0.tgz
cd imagick-2.3.0/
/usr/local/webserver/php/bin/phpize
./configure –with-php-config=/usr/local/webserver/php/bin/php-config
make
make install
cd ../
5, modify the php.ini file
Review: find /usr/local/webserver/php/etc/php.ini the extension_dir = “. /”
Amended to read extension_dir = “/usr/local/webserver/php/lib/php/extensions/no-debug-non-
zts-20060613 /”
And after this line add the following lines, then save:
extension = “memcache.so”
extension = “pdo_mysql.so”
extension = “imagick.so”
Then find output_buffering = Off
Revised to output_buffering = On
Look again; cgi.fix_pathinfo = 0
Revised cgi.fix_pathinfo = 0, to prevent the file type error parsing vulnerability Nginx.
6, configure eAccelerator accelerated PHP:
mkdir -p /usr/local/webserver/eaccelerator_cache
vi /usr/local/webserver/php/etc/php.ini
Skip to press shift + g key configuration files at the very end, add the following configuration information:
[eaccelerator]
zend_extension=”/usr/local/webserver/php/lib/php/extensions/no-debug-non-
zts-20060613/eaccelerator.so”
11. eaccelerator.shm_size=”64″
eaccelerator.cache_dir=”/usr/local/webserver/eaccelerator_cache”
eaccelerator.enable=”1″
eaccelerator.optimizer=”1″
eaccelerator.check_mtime=”1″
eaccelerator.debug=”0″
eaccelerator.filter=”"
eaccelerator.shm_max=”0″
eaccelerator.shm_ttl=”3600″
eaccelerator.shm_prune_period=”3600″
eaccelerator.shm_only=”0″
eaccelerator.compress=”1″
eaccelerator.compress_level=”9″
7, create www user and group, as well as for blog.950buy.com and www.950buy.com two virtual
hosts using the directory:
/usr/sbin/groupadd www
/usr/sbin/useradd -g www www
mkdir -p /data0/htdocs/blog
chmod +w /data0/htdocs/blog
chown -R www:www /data0/htdocs/blog
mkdir -p /data0/htdocs/www
chmod +w /data0/htdocs/www
chown -R www:www /data0/htdocs/www
8, create php-fpm configuration file (php-fpm is a fight for the PHP FastCGI patch management,
you can change the php.ini configuration without the need for a smooth restart php-cgi):
In /usr/local/webserver/php/etc/directory to create php-fpm.conf file:
rm -f /usr/local/webserver/php/etc/php-fpm.conf
vi /usr/local/webserver/php/etc/php-fpm.conf
Enter the following (if you install Nginx + PHP for debugging, set the following <value
name=”display_errors”> 0 </ value> to <value name=”display_errors”> 1 </ value>, to display PHP error
message, otherwise, Nginx will report a blank state of 500 error page):
<?xml version=”1.0″ ?>
<configuration>
All relative paths in this config are relative to php’s install prefix
<section name=”global_options”>
Pid file
<value name=”pid_file”>/usr/local/webserver/php/logs/php-fpm.pid</value>
Error log file
<value name=”error_log”>/usr/local/webserver/php/logs/php-fpm.log</value>
Log level
<value name=”log_level”>notice</value>
12. When this amount of php processes exited with SIGSEGV or SIGBUS …
<value name=”emergency_restart_threshold”>10</value>
… in a less than this interval of time, a graceful restart will be initiated.
Useful to work around accidental curruptions in accelerator’s shared memory.
<value name=”emergency_restart_interval”>1m</value>
Time limit on waiting child’s reaction on signals from master
<value name=”process_control_timeout”>5s</value>
Set to ‘no’ to debug fpm
<value name=”daemonize”>yes</value>
</section>
<workers>
<section name=”pool”>
Name of pool. Used in logs and stats.
<value name=”name”>default</value>
Address to accept fastcgi requests on.
Valid syntax is ‘ip.ad.re.ss:port’ or just ‘port’ or ‘/path/to/unix/socket’
<value name=”listen_address”>127.0.0.1:9000</value>
<value name=”listen_options”>
Set listen(2) backlog
<value name=”backlog”>-1</value>
Set permissions for unix socket, if one used.
In Linux read/write permissions must be set in order to allow connections from web server.
Many BSD-derrived systems allow connections regardless of permissions.
<value name=”owner”></value>
<value name=”group”></value>
<value name=”mode”>0666</value>
</value>
Additional php.ini defines, specific to this pool of workers.
<value name=”php_defines”>
<value name=”sendmail_path”>/usr/sbin/sendmail -t -i</value>
<value name=”display_errors”>0</value>
</value>
Unix user of processes
<value name=”user”>www</value>
Unix group of processes
<value name=”group”>www</value>
Process manager settings
<value name=”pm”>
Sets style of controling worker process count.
Valid values are ‘static’ and ‘apache-like’
<value name=”style”>static</value>
Sets the limit on the number of simultaneous requests that will be served.
Equivalent to Apache MaxClients directive.
Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi
13. Used with any pm_style.
<value name=”max_children”>128</value>
Settings group for ‘apache-like’ pm style
<value name=”apache_like”>
Sets the number of server processes created on startup.
Used only when ‘apache-like’ pm_style is selected
<value name=”StartServers”>20</value>
Sets the desired minimum number of idle server processes.
Used only when ‘apache-like’ pm_style is selected
<value name=”MinSpareServers”>5</value>
Sets the desired maximum number of idle server processes.
Used only when ‘apache-like’ pm_style is selected
<value name=”MaxSpareServers”>35</value>
</value>
</value>
The timeout (in seconds) for serving a single request after which the worker process will be
terminated
Should be used when ‘max_execution_time’ ini option does not stop script execution for some
reason
’0s’ means ‘off’
<value name=”request_terminate_timeout”>0s</value>
The timeout (in seconds) for serving of single request after which a php backtrace will be dumped to
slow.log file
’0s’ means ‘off’
<value name=”request_slowlog_timeout”>0s</value>
The log file for slow requests
<value name=”slowlog”>logs/slow.log</value>
Set open file desc rlimit
<value name=”rlimit_files”>65535</value>
Set max core size rlimit
<value name=”rlimit_core”>0</value>
Chroot to this directory at the start, absolute path
<value name=”chroot”></value>
Chdir to this directory at the start, absolute path
<value name=”chdir”></value>
Redirect workers’ stdout and stderr into main error log.
If not set, they will be redirected to /dev/null, according to FastCGI specs
<value name=”catch_workers_output”>yes</value>
How much requests each process should execute before respawn.
Useful to work around memory leaks in 3rd party libraries.
For endless request processing please specify 0
14. Equivalent to PHP_FCGI_MAX_REQUESTS
<value name=”max_requests”>1024</value>
Comma separated list of ipv4 addresses of FastCGI clients that allowed to connect.
Equivalent to FCGI_WEB_SERVER_ADDRS environment in original php.fcgi (5.2.2+)
Makes sense only with AF_INET listening socket.
<value name=”allowed_clients”>127.0.0.1</value>
Pass environment variables like LD_LIBRARY_PATH
All $VARIABLEs are taken from current environment
<value name=”environment”>
<value name=”HOSTNAME”>$HOSTNAME</value>
<value name=”PATH”>/usr/local/bin:/usr/bin:/bin</value>
<value name=”TMP”>/tmp</value>
<value name=”TMPDIR”>/tmp</value>
<value name=”TEMP”>/tmp</value>
<value name=”OSTYPE”>$OSTYPE</value>
<value name=”MACHTYPE”>$MACHTYPE</value>
<value name=”MALLOC_CHECK_”>2</value>
</value>
</section>
</workers>
</configuration>
9, start php-cgi processes, monitor port 9000 of 127.0.0.1, the process number of 128 (if the
server memory is less than 3GB, you can only open 64 process), the user is www
ulimit -SHn 65535
/usr/local/webserver/php/sbin/php-fpm start
Description: /usr/local/webserver/php/sbin/php-fpm there are other parameters, including: start | stop |
quit | restart | reload | logrotate, modify php.ini does not restart after the php-cgi, re-load the
configuration file using the reload.
Third, install Nginx 0.8.46
1, install Nginx required pcre library:
tar zxvf pcre-8.10.tar.gz
cd pcre-8.10/
./configure
make && make install
cd ../
2, install Nginx
tar zxvf nginx-0.8.46.tar.gz
cd nginx-0.8.46/
./configure –user=www –group=www –prefix=/usr/local/webserver/nginx –with-http_stub_status_module
–with-http_ssl_module
15. make && make install
cd ../
3, to create the log directory Nginx
mkdir -p /data1/logs
chmod +w /data1/logs
chown -R www:www /data1/logs
4, create Nginx configuration file
A, In /usr/local/webserver/nginx/conf/ directory to create nginx.conf file
rm -f /usr/local/webserver/nginx/conf/nginx.conf
vi /usr/local/webserver/nginx/conf/nginx.conf
Enter the following:
user www www;
worker_processes 8;
error_log /data1/logs/nginx_error.log crit;
pid /usr/local/webserver/nginx/nginx.pid;
#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 65535;
events
{
use epoll;
worker_connections 65535;
}
http
{
include mime.types;
default_type application/octet-stream;
#charset utf-8;
server_names_hash_bucket_size 128;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 8m;
sendfile on;
tcp_nopush on;
keepalive_timeout 60;
tcp_nodelay on;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;