NginX reverse proxy

NginX is a high performance, lightweight webserver. In most situations, it is used as an alternative to Apache. However, in the configurations with cPanel, typical protocol is to install it as a reverse proxy.

Reverse proxy

NginX runs as a reverse proxy server. In a normal proxy situation, a user makes a request to a server through a proxy. The user and the server never interact directly-- the proxy makes the request on behalf of the user. Likewise, the proxy hands the responses from the server back to the user.
A reverse proxy works by the same concept-- it's just a proxy that works on behalf of the server instead of the user. Rather than having Apache process requests directly, NginX takes them, finds any requests it is best suited to satisfy (such as static content) and forwards the rest on to Apache. Apache gives its response to NginX, and NginX sends the response to the client. If NginX finds itself able to serve a request directly, it does so and never involves Apache at all.

Implications

This requires several key changes in the configuration and serving model:
  • Apache can no longer run on port 80 for this to work. Apache has to move to another port (preferably behind a firewall) in order to serve requests from NginX. NginX then runs on port 80.
  • Requests to Apache now all come from 127.0.0.1. Without a Real-IP translation module, some things that rely on knowing what the destination user's IP is will break.
  • NginX is not managed by cPanel and so if configuration changes are made on Apache's end, it may not necessarily know about them.
These are major changes that should not be taken lightly. In most cases, you should strive to avoid installing NginX. This article serves to give you an idea of when NginX is and isn't appropriate. Installing NginX makes a system much harder to maintain.

Overview of serving models

NginX has some very notable strengths. The primary one is its non-blocking connection model. A typical Apache worker process or thread handles a couple request like this:
  1. Client A attempts to connect.
  2. Client B attempts to connect.
  3. Client A's connection establishes with Apache.
  4. Client A requests a PHP page.
  5. PHP renders the page and sends it to Apache
  6. Apache sends the result to Client A.
  7. Apache closes the connection to Client A.
  8. Client B's connection establishes with Apache.
  9. Client B requests an image file.
  10. Apache fetches the image
  11. Apache sends the image to the Client B.
  12. Apache closes the connection to Client B.
The key thing to notice here is that until Client A was completely finished, Client B's connection did not even establish. Apache had to wait until PHP was finished to serve Client B's request. By contrast, NginX's worker process or thread would serve the same two requests like this:
  1. Client A attempts to establish a connection
  2. Client B attempts to establish a connection
  3. NginX establishes a connection with Client A
  4. NginX establishes a connection to Client B
  5. Client A makes a PHP request.
  6. Client B makes an image request
  7. NginX goes to fetch the PHP request
  8. NginX goes to fetch the image request
  9. NginX sends the image requested to client B
  10. NginX closes the connection to Client B
  11. NginX gets processed page from PHP and sends it back to Client A
  12. NginX closes the connection to Client A
The big difference here is that NginX did not force the next request to wait in line. It picked it up as soon as it picked up the previous one. Apache is able to get similar performance in most circumstances by having several threads. NginX, on the other hand, has this capability within each of its threads, rotating to pick up and serve a request at a time as they come in.
However, if we want cPanel in the mix, we can only use NginX as a reverse proxy, and thus do not have just one or the other. We attempt to combine the two servers, and the result looks more like this:
  1. Client A attempts to establish a connection
  2. Client B attempts to establish a connection
  3. NginX establishes a connection with Client A
  4. NginX establishes a connection with Client B
  5. Client A requests a PHP page
  6. Client B requests an image file
  7. NginX passes Client A's request to Apache
  8. NginX serves the image file to Client B
  9. Apache fetches the result from PHP
  10. NginX closes the connection to Client B
  11. Apache returns the result of the PHP request to NginX
  12. NginX sends the result from Apache to Client A
  13. NginX closes the connection to Client A
The image file is not blocked in this request, but PHP does have to make an extra hop.
In version 1 of Apache, static requests were slow enough that switching to NginX for static files netted considerable benefit, especially when using PHP as a Dynamic Shared Object. This caused less memory to be used and requests to static images were not blocked by PHP requests.
These days, Apache's static file serving is very fast, and when PHP is configured with a CGI model like SuPHP, CGI, or FCGI, it does not have the bloat of the entirety of PHP in each process. With multiple threads, Apache is able to close the speed gap between itself and NginX in almost all cases.

When NginX is appropriate

NginX is most helpful when dealing with sites that have a lot of mobile users which don't necessarily have high intensity requests, but may have a high volume of them with a very long latency. Apache processes and threads would have trouble with its request blocking model, as the full transactions would need to be stretched out and shortening the keep alive time is not an option when all of your customers have slow connections. An example of this would be sites geared towards Mobile phones, which have high latency.
NginX can also be helpful when mitigating certain types of DDoS attacks. It is most helpful in SlowLoris style attacks where the blocking nature of Apache's worker threads is exploited. However, it should be noted that NginX's defaults do not mitigate most DDoS attacks and its settings must be adjusted to get proper performance under duress. You should always try other techniques before using NginX.
If for some reason, an Apache 2 server must run prefork, NginX could improve performance considerably. The reasons for running Prefork in the first place are few and far between-- it is a legacy MPM for non-thread safe Apache modules.

When NginX is NOT appropriate

NginX is not very effective as a page speed booster with modern versions of Apache. The majority of the benefit, in terms of speed, is usually matched by Apache's multiple threads, except in the case where the type of request causes IO blocking issues, as mentioned above.
NginX does not provide much speed boost in sending static files. Apache's latest versions with threaded MPMs allow lightweight image requests to be served promptly. The exception to this might be if the number of images a site has is truly staggering.
NginX, especially when put as a reverse proxy, will not grant additional capacity to hardware that is getting a large amount of legitimate requests. If you are installing NginX to deal with a high traffic site that really is just that popular, you'd likely be better off just upgrading the hardware, or customer should get a consultant to work on a load balancing structure.
If NginX would normally be appropriate, but static files are only accessed through Apache mod_rewrite rules, NginX's benefit is negated.

Installation

$ cd /usr/local/src
$ wget http://nginxcp.com/latest/nginxadmin.tar
$ tar xf nginxadmin.tar
$ cd publicnginx
$ ./nginxinstaller install


Note:
You may needed to run pythonfix script if you are installing it in first time.
Id you have previously installed old version of the nginx admin, please uninstall and then perform the installation.
After installation, you will be given some additional directions:
/usr/local/cpanel/whostmgr/bin/whostmgr2 --updatetweaksettings && service nginx start
...must be run in order to finish the transition and change Apache over to port 81.
The following cron job should be added to the root crontab:
* * * * * /opt/nginx/scripts/apache-conf-check &>/dev/null
This script checks to see if any changes have been made to the httpd.conf file, and if they have, it rebuilds NginX's vhost list to add new entries for them by running this script:
/opt/nginx/scripts/build-nginx-vhosts
...and then reloading NginX's configuration with:
service nginx reload
If this is not happening automatically, make sure the cron job has been installed correctly and that the scripts are able to run.

Uninstallation

$ cd /usr/local/src
$ wget http://nginxcp.com/latest/nginxadmin.tar
$ tar xf nginxadmin.tar
$ cd publicnginx
$ ./nginxinstaller uninstall


Then, run:
/usr/local/cpanel/whostmgr/bin/whostmgr2 --updatetweaksettings
...to switch Apache back over to port 80.
Finally, remove this cron job from the root crontab:
* * * * * /opt/nginx/scripts/apache-conf-check &>/dev/null

Comments

Popular posts from this blog

SVN: File remains in conflict

HowTo: Enable extended logging for exim

12 tweakings for WHM/cPanel to speed up WordPress