nginx + php_fpm vs nginx reverse proxy + apache mod_php vs apache mod_php
There are several ways to run PHP on your webserver.
The most popular is to use Apache2 mod_php . It is native way, supported out of the box on most of Linux distributions. If you use hosting with cPanel, this is the most likely way apache is running.
Second popular way is to use nginx + php_fpm (PHP FastCGI Process Manager). It is used on several high performance websites.
From PHP 5.4 or so, php_fpm is part of PHP and is quite stable. Lots of Linux distributions have this as optional PHP package.
It is important to be noted that nginx + php_fpm does not support .htaccess files, so programmers need to make changes to their hosting configurations. With nginx + php_fpm, hosting of legacy applications is almost impossible.
Speaking of high-performance PHP, there is third way that is not widely used. It uses nginx as frontend and Apache2 webserver with mod_php as backend (called nginx + apache mod_php).
With this third way you have the best of both worlds - blazing fast static content and familiar Apache features like .htaccess files in one "package".
Downside of this method is setup complexity.
All tests were performed on 4 core AMD Opteron 3280 with 16 GB RAM and SATA HDD.
Software versions are as follows:
Apache2 had following configuration
#StartServers 5 MinSpareServers 100 MaxSpareServers 200
This means Apache2 will do almost no forks after initial requests. This is trading speed for system resources.
PHP FPM was set up in similar way:
pm.start_servers = 100 pm.min_spare_servers = 100 pm.max_spare_servers = 200
TCP stack was in "turbo" mode, e.g. tcp_tw_recycle, tcp_tw_reuse.
Test were made with Apache's ab.
Before making any tests, we need to have some baseline. This is why we decided to check simple HTML file transfer.
Test over localhost:
requests per second | ||
---|---|---|
no keep alive | keep alive | |
nginx | 10,172 | not tested |
apache2 | 6,599 | not tested |
Same test over the internet LAN produced similar even faster result !!!
requests per second | ||
---|---|---|
no keep alive | keep alive | |
nginx | 12,663 | 34,898 |
apache2 | 7,054 | 28,818 |
Interestingly both servers worked smoothly without making any spikes in load average.
As expected Apache2 uses more resources.
For all tests we used very simple PHP file:
<?php echo "Hello World";
Tests over localhost:
requests per second | ||
---|---|---|
no keep alive | keep alive | |
nginx + php_fpm | 9,681 | 54,579 |
nginx + apache2 mod_php | 8,571 | 26,034 |
apache2 mod_php | 6,550 | same |
It was surprising that apache2 mod_php performed slower that nginx + apache2 mod_php. We believe this is because nginx gets and handle the client request and forwarding it to the Apache2 server with internal keep-alive.
"Real" tests over internet LAN:
requests per second | ||
---|---|---|
no keep alive | keep alive | |
nginx + php_fpm | 11,977 | 29,053 |
nginx + apache2 mod_php | 11,197 | 24,134 |
apache2 mod_php | 6,992 | 22,673 |
We did perform this test several times.
It is very important that current Apache2 config favours lots of requests.
This means if you perform the test several times, first time you will get lower result and after that you will consistently get higher result.
Another very important consideration is that current Apache2 config had .htaccess files were turned on.
If .htaccess is turned off, results were almost the same.
Apache2 is about 40-50% slower than nginx if you do serve static content, but is still fast enought (~7K requests per second) for most websites.
Apache2 .htaccess is slow. If you can, switch it off.
php_fpm is faster than mod_php, but with just 9 - 10%.
This difference of 10% for sure will go away,
if you have real workload with real business logic and database like MySQL, PostgreSQL or even Redis.
This is confirmed from a college who did measure nginx vs Apache2.
Local nginx static file ======================= Server Software: nginx Server Hostname: 100.100.100.100 Server Port: 80 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 9.831 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 25891848 bytes HTML transferred: 1204272 bytes Requests per second: 10172.35 [#/sec] (mean) Time per request: 78.645 [ms] (mean) Time per request: 0.098 [ms] (mean, across all concurrent requests) Transfer rate: 2572.08 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 16 35 6.0 34 53 Processing: 18 44 8.2 43 77 Waiting: 2 32 9.6 30 65 Total: 51 78 5.9 78 100 Percentage of the requests served within a certain time (ms) 50% 78 66% 81 75% 82 80% 83 90% 86 95% 87 98% 90 99% 92 100% 100 (longest request) Local Apache2 static file ========================= Server Software: Apache/2.2.32 Server Hostname: 85.25.133.33 Server Port: 8080 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 15.154 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 29701782 bytes HTML transferred: 1200072 bytes Requests per second: 6599.10 [#/sec] (mean) Time per request: 121.229 [ms] (mean) Time per request: 0.152 [ms] (mean, across all concurrent requests) Transfer rate: 1914.11 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 35 110.6 27 3029 Processing: 1 56 520.6 31 15117 Waiting: 0 49 520.8 24 15117 Total: 14 91 533.0 60 15148 Percentage of the requests served within a certain time (ms) 50% 60 66% 66 75% 70 80% 73 90% 79 95% 83 98% 95 99% 1039 100% 15148 (longest request) LAN nginx static file ===================== Server Software: nginx Server Hostname: 100.100.100.100 Server Port: 80 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 7.896 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 25800000 bytes HTML transferred: 1200000 bytes Requests per second: 12663.98 [#/sec] (mean) Time per request: 63.171 [ms] (mean) Time per request: 0.079 [ms] (mean, across all concurrent requests) Transfer rate: 3190.73 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 1 40 189.4 5 3014 Processing: 1 19 67.8 5 5046 Waiting: 1 18 67.7 5 5046 Total: 3 59 207.0 10 6053 Percentage of the requests served within a certain time (ms) 50% 10 66% 12 75% 15 80% 18 90% 34 95% 222 98% 1012 99% 1017 100% 6053 (longest request) LAN Apache2 static file ======================= Server Software: Apache/2.2.32 Server Hostname: 100.100.100.100 Server Port: 8080 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 14.176 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Total transferred: 29700000 bytes HTML transferred: 1200000 bytes Requests per second: 7054.33 [#/sec] (mean) Time per request: 113.406 [ms] (mean) Time per request: 0.142 [ms] (mean, across all concurrent requests) Transfer rate: 2046.03 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 91 348.4 4 7020 Processing: 1 17 88.3 7 2535 Waiting: 1 17 88.3 7 2535 Total: 2 109 359.6 12 7029 Percentage of the requests served within a certain time (ms) 50% 12 66% 14 75% 16 80% 17 90% 218 95% 1013 98% 1020 99% 1026 100% 7029 (longest request) LAN nginx static file + keep alive ================================== Server Software: nginx Server Hostname: 100.100.100.100 Server Port: 80 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 2.865 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Keep-Alive requests: 100000 Total transferred: 26300000 bytes HTML transferred: 1200000 bytes Requests per second: 34898.06 [#/sec] (mean) Time per request: 22.924 [ms] (mean) Time per request: 0.029 [ms] (mean, across all concurrent requests) Transfer rate: 8963.08 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.9 0 27 Processing: 10 23 2.5 23 58 Waiting: 10 23 2.5 23 58 Total: 10 23 3.0 23 77 Percentage of the requests served within a certain time (ms) 50% 23 66% 23 75% 23 80% 23 90% 23 95% 23 98% 31 99% 37 100% 77 (longest request) LAN Apache2 static file + keep alive ==================================== Server Software: Apache/2.2.32 Server Hostname: 100.100.100.100 Server Port: 8080 Document Path: / Document Length: 12 bytes Concurrency Level: 800 Time taken for tests: 3.470 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Keep-Alive requests: 99186 Total transferred: 33264349 bytes HTML transferred: 1200000 bytes Requests per second: 28818.03 [#/sec] (mean) Time per request: 27.760 [ms] (mean) Time per request: 0.035 [ms] (mean, across all concurrent requests) Transfer rate: 9361.45 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.5 0 25 Processing: 1 13 66.0 7 2907 Waiting: 1 13 66.0 7 2907 Total: 1 13 66.9 7 2931 Percentage of the requests served within a certain time (ms) 50% 7 66% 7 75% 7 80% 7 90% 8 95% 8 98% 10 99% 28 100% 2931 (longest request)
Local nginx + php_fpm ===================== Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 80 Document Path: /x1.php Document Length: 162 bytes Concurrency Level: 800 Time taken for tests: 10.329 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100271 Total transferred: 32888888 bytes HTML transferred: 16243902 bytes Requests per second: 9681.94 [#/sec] (mean) Time per request: 82.628 [ms] (mean) Time per request: 0.103 [ms] (mean, across all concurrent requests) Transfer rate: 3109.65 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 1 34 5.5 34 53 Processing: 9 48 20.9 46 298 Waiting: 3 37 21.6 36 287 Total: 11 82 19.5 81 325 Percentage of the requests served within a certain time (ms) 50% 81 66% 84 75% 86 80% 87 90% 89 95% 92 98% 98 99% 102 100% 325 (longest request) Local nginx + php_fpm + keep alive ================================== Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 80 Document Path: /x1.php Document Length: 162 bytes Concurrency Level: 800 Time taken for tests: 1.832 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100446 Keep-Alive requests: 100000 Total transferred: 33448518 bytes HTML transferred: 16272252 bytes Requests per second: 54579.11 [#/sec] (mean) Time per request: 14.658 [ms] (mean) Time per request: 0.018 [ms] (mean, across all concurrent requests) Transfer rate: 17828.03 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 2.4 0 40 Processing: 0 14 9.7 10 66 Waiting: 0 14 9.7 10 66 Total: 0 14 10.1 10 80 Percentage of the requests served within a certain time (ms) 50% 10 66% 15 75% 17 80% 19 90% 31 95% 36 98% 42 99% 47 100% 80 (longest request) Local nginx + apache mod_php ============================ Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 81 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 11.667 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100224 Total transferred: 41392512 bytes HTML transferred: 20445696 bytes Requests per second: 8571.35 [#/sec] (mean) Time per request: 93.334 [ms] (mean) Time per request: 0.117 [ms] (mean, across all concurrent requests) Transfer rate: 3464.74 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 36 6.4 36 61 Processing: 4 57 14.1 56 305 Waiting: 2 43 13.8 44 289 Total: 9 93 13.8 93 333 Percentage of the requests served within a certain time (ms) 50% 93 66% 97 75% 100 80% 101 90% 107 95% 114 98% 124 99% 134 100% 333 (longest request) Local nginx + apache mod_php + keep alive ========================================= Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 81 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 3.841 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100006 Keep-Alive requests: 100000 Total transferred: 41802508 bytes HTML transferred: 20401224 bytes Requests per second: 26034.79 [#/sec] (mean) Time per request: 30.728 [ms] (mean) Time per request: 0.038 [ms] (mean, across all concurrent requests) Transfer rate: 10628.12 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 2.5 0 44 Processing: 0 24 55.6 13 3037 Waiting: 0 24 55.6 13 3037 Total: 0 24 57.0 13 3056 Percentage of the requests served within a certain time (ms) 50% 13 66% 19 75% 24 80% 29 90% 57 95% 72 98% 83 99% 98 100% 3056 (longest request) Local apache mod_php ==================== Server Software: Apache/2.2.32 Server Hostname: 85.25.133.33 Server Port: 8080 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 6.746 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100175 Keep-Alive requests: 99409 Total transferred: 45253740 bytes HTML transferred: 20435700 bytes Requests per second: 14823.03 [#/sec] (mean) Time per request: 53.970 [ms] (mean) Time per request: 0.067 [ms] (mean, across all concurrent requests) Transfer rate: 6550.76 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 5.3 0 55 Processing: 2 49 178.9 39 3928 Waiting: 2 49 178.9 39 3928 Total: 2 49 181.5 39 3978 Percentage of the requests served within a certain time (ms) 50% 39 66% 41 75% 43 80% 45 90% 47 95% 49 98% 52 99% 83 100% 3978 (longest request) LAN nginx + php_fpm =================== Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 80 Document Path: /x1.php Document Length: 162 bytes Concurrency Level: 800 Time taken for tests: 8.349 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Total transferred: 32800000 bytes HTML transferred: 16200000 bytes Requests per second: 11977.39 [#/sec] (mean) Time per request: 66.793 [ms] (mean) Time per request: 0.083 [ms] (mean, across all concurrent requests) Transfer rate: 3836.51 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 47 231.2 4 3013 Processing: 1 15 48.5 5 893 Waiting: 1 15 48.4 4 893 Total: 2 63 238.1 9 3228 Percentage of the requests served within a certain time (ms) 50% 9 66% 9 75% 10 80% 11 90% 25 95% 216 98% 1011 99% 1013 100% 3228 (longest request) LAN nginx + php_fpm + keep alive ================================ Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 80 Document Path: /x1.php Document Length: 162 bytes Concurrency Level: 800 Time taken for tests: 3.442 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Keep-Alive requests: 100000 Total transferred: 33300000 bytes HTML transferred: 16200000 bytes Requests per second: 29053.51 [#/sec] (mean) Time per request: 27.535 [ms] (mean) Time per request: 0.034 [ms] (mean, across all concurrent requests) Transfer rate: 9448.07 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 2.8 0 43 Processing: 10 27 2.8 27 42 Waiting: 10 27 2.8 27 42 Total: 10 27 3.7 27 66 Percentage of the requests served within a certain time (ms) 50% 27 66% 27 75% 28 80% 28 90% 31 95% 32 98% 36 99% 40 100% 66 (longest request) LAN nginx + apache mod_php ========================== Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 81 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 8.930 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Total transferred: 41300000 bytes HTML transferred: 20400000 bytes Requests per second: 11197.86 [#/sec] (mean) Time per request: 71.442 [ms] (mean) Time per request: 0.089 [ms] (mean, across all concurrent requests) Transfer rate: 4516.33 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 27 158.2 5 3010 Processing: 1 36 206.8 8 4567 Waiting: 1 36 206.7 8 4564 Total: 1 63 262.5 14 7307 Percentage of the requests served within a certain time (ms) 50% 14 66% 18 75% 21 80% 24 90% 37 95% 219 98% 1016 99% 1066 100% 7307 (longest request) LAN nginx + apache mod_php + keep alive ======================================= Server Software: nginx Server Hostname: 85.25.133.33 Server Port: 81 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 4.143 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Keep-Alive requests: 100000 Total transferred: 41800000 bytes HTML transferred: 20400000 bytes Requests per second: 24134.79 [#/sec] (mean) Time per request: 33.147 [ms] (mean) Time per request: 0.041 [ms] (mean, across all concurrent requests) Transfer rate: 9851.90 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 2.4 0 40 Processing: 1 24 114.0 13 3819 Waiting: 1 24 114.0 13 3819 Total: 1 24 115.1 13 3819 Percentage of the requests served within a certain time (ms) 50% 13 66% 15 75% 16 80% 18 90% 22 95% 27 98% 32 99% 73 100% 3819 (longest request) LAN apache mod_php ================== Server Software: Apache/2.2.32 Server Hostname: 85.25.133.33 Server Port: 8080 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 14.302 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Total transferred: 41600000 bytes HTML transferred: 20400000 bytes Requests per second: 6992.27 [#/sec] (mean) Time per request: 114.412 [ms] (mean) Time per request: 0.143 [ms] (mean, across all concurrent requests) Transfer rate: 2840.61 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 95 342.1 4 7018 Processing: 1 14 39.6 6 831 Waiting: 1 14 39.6 6 831 Total: 2 109 344.9 11 7030 Percentage of the requests served within a certain time (ms) 50% 11 66% 13 75% 14 80% 16 90% 218 95% 1013 98% 1018 99% 1022 100% 7030 (longest request) LAN apache mod_php + keep alive =============================== Server Software: Apache/2.2.32 Server Hostname: 85.25.133.33 Server Port: 8080 Document Path: /x1.php Document Length: 204 bytes Concurrency Level: 800 Time taken for tests: 4.410 seconds Complete requests: 100000 Failed requests: 0 Write errors: 0 Non-2xx responses: 100000 Keep-Alive requests: 99309 Total transferred: 45170301 bytes HTML transferred: 20400000 bytes Requests per second: 22673.76 [#/sec] (mean) Time per request: 35.283 [ms] (mean) Time per request: 0.044 [ms] (mean, across all concurrent requests) Transfer rate: 10001.76 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 2 35.7 0 1032 Processing: 3 33 54.8 30 1425 Waiting: 3 33 54.8 30 1425 Total: 3 34 86.2 30 2457 Percentage of the requests served within a certain time (ms) 50% 30 66% 30 75% 30 80% 31 90% 31 95% 32 98% 34 99% 128 100% 2457 (longest request)