Search This Blog

Friday, March 16, 2012

How to configure Nginx and Apache on Debian | Linux

How to configure Nginx and Apache on Debian | Linux:


I have heard about nginx the light weight and very fast webserver and many of my friends are using it on production for static contents. But I'm running multiple CMS sites, it is not easy at all to separate static contents or images from CMS path to another server. So I was looking for the solution that can run nginx for static contents and run apache for dynamic contents (php) on the same server.

The Story

After I ran my production site MEEDEE.NET for several months until get Unique IP up to 5,000 - 8,000 per day. I think it is a good time to redesign my template with a new looking and features. The slow page loading problem was occured when I changed my Joomla! template to T3 Framework byJoomlart, It consume much more resources and with high traffic can cause very slow page loading.
The problem is quite severe than I expected, because apache crashed almost everyday, we have to monitor frequently when it gonna happen. Unfortunately, my server is ruuning on Debian VPS with 8 GB shared memory, when the traffic is too high, it generate a lot of apache processes and consume memory up to 6 GB and many high cpu processes. This situation will cause all VPS on the same physical server crashed as well.

Apache MPM

So, I was looking for a solution. I'm not a linux geek guy, if the problem is apache, let fix on apache. I was checking the information about Apahce MPM (Multi-Processing Modules). There are 2 common MPM mode on Linux, prefork and worker. There are so many articles cheer up that worker mode is better, and faster. But very few aarticles mention that it doesn't support php! There are also many articles talking about how to run php on apache in worker mode via fast-cgi, but they also mentioned about foreseen problems as well and it even officially not recommended by php.net (read here:http://php.net/manual/en/install.unix.apache2.php). So, I decided not to touch this issue and look for another solution.

NginX

I have heard nginx for long time. It's extremely fast and very low resource consumption. There are many cases study about performance has improve drastically after nginx implementation. But it also more problematic as well. First of all it does not support php on the fly, we have to do it via cgi as well (and the instruction looks very difficult to me). Second, it is not support .htaccess file. So my life will be more difficult to maintain many CMS sites and have to take care all configurations.

The Solution

The most interesting solution to me is running both NginX and Apache on the same server. There are many people also looking for the same issue. So, the original idea of this solution is let nginx handle static contents, and apahce take care for dynamic contents on the same server.

NignX for static contents

From my understood, the original strength of nginx is fast webserver for static contents anyway. So, let it do its expertise. We put nginx on front tier on port 80 to handle all http requests. If the request is static contents (iamges, text, zip, css, javascript, etc.) it will handle immediatly without writing access log. While all other request will be proxy pass to Apache on other port.

Apache for dynamic contents

I was a little bit nervous at the beginning to change default apache port from 80 to another, but after did it, it's not difficult at all. In my case I just change only line in/etc/apahce2/port.conf from Listen 80 to Listen 8080 and that's all! No need to touch an virtualhost configuration. I still leave apahce handle port 443 directly, nginx listen on port 80 only. It means apache will handle all php and mysql query and provide output to nginx, then nginx provide output to your web browser.

Implementation

Installation

In former time, it quite difficult to install nginx on Debian or Ubuntu, We have to download, install and compile it manually. Now nginx is part of Debian repository and it can install via aptitude.
aptitude install nginx

Configuration

In my case, there are many Joomla! site, but only few of them has high traffic, and I'm too lazy to configure all virtualhost on nginx. So, I put nginx default to forward all requests to apahce, then I configure nginx virtualhost only the sites I like nginx to handle static contents. The trick is root directive, we need to set root directive in every nignx virtualhost individually to make nginx khows where to find image files.

Change Apache Listening Port

In debian or ubuntu, you can configure Apache listening port with command line:
sudo nano /etc/apache2/ports.conf
change from:
Listen 80
to:
Listen 8080

Example nginx configuration

Edit nginx configuration with command line:
sudo nano /etc/nginx/sites-available/default
This is my default configuration guideline.
###############################################################################
# default
###############################################################################

# Default by nginx guideline
client_header_timeout  3m;
client_body_timeout    3m;
send_timeout           3m;

client_header_buffer_size    1k;
large_client_header_buffers  4 4k;

client_max_body_size       100m;
client_body_buffer_size    128k;

# Hash Table
server_names_hash_bucket_size 64;

# Proxy
proxy_connect_timeout      90;
proxy_send_timeout         90;
proxy_read_timeout         90;
 
proxy_buffer_size          4k;
proxy_buffers              4 32k;
proxy_busy_buffers_size    64k;
proxy_temp_file_write_size 64k;

server {
    listen   80 default;

    # Dydamic Content forward to Apache
    location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8080;
    }
}

###############################################################################
# virtualhost
###############################################################################

server {
    server_name www.example.com example.com;
    root /path/to/html/root/;

    # Static Contents
    location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
        access_log off;
        expires 30d;
    }

    # Dydamic Content forward to Apache
    location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8080;
    }
}

server {
    server_name another.example.com;
    root /path/to/another/html/root/;

    # Static Contents
    location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
        access_log off;
        expires 30d;
    }

    # Dydamic Content forward to Apache
    location / {
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8080;
    }
}

server {
    server_name images.example.com;
    root /path/to/images/root/;

    # Static Contents
    location ~* ^.+.(jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$ {
        access_log off;
        expires 30d;
    }

}

reverse proxy add forward module for Apache (mod_rpaf)

In Nginx, you will see this line: proxy_set_header X-Real-IP $remote_addr; and I thought it will work fine without further configuration on Apache. I found the problem later on when all the Apache requests came from itself! all the remote IP in the log file are 127.0.0.1.
The real problem happens when all my comments in my sites are from localhost (127.0.0.1). Actually, I found the solution from the beginning but I was afraid to implement it, since it not written officially on Nginx website, and I thought this module was not in Debian repository, my big mistake.
I just tried to find the solution again and found out that this module also in Debian repository. There were some instruction to add RPAFheader X-Forwarded-For in the rpaf.conf, but in my case it just works fine after installation without any configuration. To install it also very simple on Debian.
sudo aptitude install libapache2-mod-rpaf

The Result

After implementation, I just found out that it seems not reduce cpu consumption at all... lol. But it reduced memory consumption during high traffic drastically (reduced from 2 GB to less than 1 GB). The memory consumption during low traffic very similar to before implementation (approx 600 - 900 MB). The page loading on web browser during high traffic is more stable, less time out and blank screen. Apache access log look cleaner in command apachetop, now it show mostly access urls, no more flooding by image urls.
CPU Consumption over 4 weeks by Bijk.com
CPU CONSUMPTION OVER 4 WEEKS BY BIJK.COM
Memory Consumption over 4 weeks by Bijk.com
MEMORY CONSUMPTION OVER 4 WEEKS BY BIJK.COM
My bottom line is it's nice to have, worth to learn and not too difficult to implement. Even it does not improve cpu consumption. But it improve memory consumption a lot and have positive effect on overall performance as well.

No comments:

Post a Comment