Here is a little bit of my experience. For a long time I`ve use a simple cooperation of Drupal + Nginx with a default hosting settings:

  server {
    listen 62.xxx.xx.xx:80;
    server_name mysite.com www.mysite.com;
    rewrite>^(/manager/.*)$>https://$host$1>permanent;
    location ~* ^/(webstat/|awstats|webmail/|myadmin/|manimg/) {
      proxy_pass http://62.xxx.xx.xx:8080;
      proxy_redirect http://mysite.com:8080/ /;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
    location / {
      proxy_pass http://mysite.com:8080;
      proxy_redirect http://mysite.com:8080/ /;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
    location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
      root /home/pathto/drupal613;
      access_log /home/httpd-logs/mysite.com.access.log;
      error_page 404 = @fallback;
    }
    location @fallback {
      proxy_pass http://62.xxx.xx.xx:8080;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }

The idea of this is really simple: unload apache, and leave it for only php and building processes, throw all static data(images, files) to Nginx. My Apache listening for the 8080 port, and Nginx 80, and throw all non-static data to 8080. This scale performance a little bit up and all works fine.

I`ve tested this scheme via LoadImpact.com service and it gives me this performance picture: http://blog.itcross.net/apache_nginx.png

As you can see, more people on the website worth to less performance and longer delay. Thats real bad. So, I`ve tried to find a solution and find it with a cooperation of:

Pressflow + Nginx + Varnish

Pressflow is a distribution of Drupal with integrated performance, scalability, availability, and testing enhancements.

Each version of Pressflow is API-compatible with the same major Drupal version. For example, Pressflow 6 is compatible with all Drupal 6 modules. Pressflow 6 also integrates the SimpleTest system from Drupal 7 and the CDN support patch. See the wiki (linked below) for more documentation.

Here is a links to download Pressflow:
http://fourkitchens.com/pressflow-makes-drupal-scale/downloads
https://launchpad.net/pressflow/+download

Varnish is the key software that speeds up your web site.

It is Open Source, built on industry standards and requires very few resources.

Here is a links to download and install Varnish:
http://www.varnish-cache.org/releases

The idea is simple too: lets check all request and response to them through Nginx if static data requested, through Varnish+Pressflow if there is some data could be taken from cache, and from Apache if we need to process something.

Step 1: Install Pressflow

Installation of Pressflow is similar as Drupal installation, generally speaking it is the same ))
http://fourkitchens.com/pressflow-makes-drupal-scale/installation

Step 2: Setup Pressflow

Just go to http://mysite.com/admin/settings/performance and enable caching. That`s it.

Step 3: Install Varnish

If you are not in touch with SSH and Linux, you can ask your hosting administrators to install Varnish. I`ve used this guide for FreeBSD http://www.varnish-cache.org/installation/freebsd. It is really simple.

Step 4: Setup Varnish

It`s on of most complex step. There are 3 main points you should follow:

1. Add varnish deamon and varnish log to /etc/rc.conf:

varnishd_enable="YES"
varnishlog_enable="YES"

2. Change default settings of varnish deamon:

: ${varnishd_enable:="NO"}
: ${varnishd_pidfile:="/var/run/${name}.pid"}
: ${varnishd_listen:=":8081"}
: ${varnishd_admin:="localhost:8090"}
: ${varnishd_backend:="localhost:8080"}
: ${varnishd_config:="/usr/local/etc/varnish/default.vcl"}
: ${varnishd_storage:="file,/usr/local/varnish.cache,1G"}
: ${varnishd_hash:="classic,16383"}
: ${varnishd_user:="www"}
: ${varnishd_group:="www"}

As you remember my Nginx server listening to 80 port, and throw non-static data to 8080(apache port). Lets make Varnish listening to 8081 port and throw responses to 8080 too.

-varnishd_config - default folder with settings for Varnish behavior
-varnishd_storage - cache file path and size

3. Setup Varnish to work with Pressflow:

backend default {
  .host = "127.0.0.1";
  .port = "8080";
  .connect_timeout = 600s;
  .first_byte_timeout = 600s;
  .between_bytes_timeout = 600s;
}

sub vcl_recv {
  if (req.request != "GET" &&
    req.request != "HEAD" &&
    req.request != "PUT" &&
    req.request != "POST" &&
    req.request != "TRACE" &&
    req.request != "OPTIONS" &&
    req.request != "DELETE") {
      /* Non-RFC2616 or CONNECT which is weird. */
      return (pipe);
  }

  if (req.request != "GET" && req.request != "HEAD") {
    /* We only deal with GET and HEAD by default */
    return (pass);
  }

  // Remove has_js and Google Analytics cookies.
  set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+)=[^;]*", "");

  // To users: if you have additional cookies being set by your system (e.g.
  // from a javascript analytics file or similar) you will need to add VCL
  // at this point to strip these cookies from the req object, otherwise
  // Varnish will not cache the response. This is safe for cookies that your
  // backed (Drupal) doesn't process.
  //
  // Again, the common example is an analytics or other Javascript add-on.
  // You should do this here, before the other cookie stuff, or by adding
  // to the regular-expression above.


  // Remove a ";" prefix, if present.
  set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");
  // Remove empty cookies.
  if (req.http.Cookie ~ "^\s*$") {
    unset req.http.Cookie;
  }

  if (req.http.Authorization || req.http.Cookie) {
    /* Not cacheable by default */
    return (pass);
  }

  // Skip the Varnish cache for install, update, and cron
  if (req.url ~ "install\.php|update\.php|cron\.php") {
    return (pass);
  }

  // Normalize the Accept-Encoding header
  // as per: http://varnish-cache.org/wiki/FAQ/Compression
  if (req.http.Accept-Encoding) {
    if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|tbz|mp3|ogg)$") {
      # No point in compressing these
      remove req.http.Accept-Encoding;
    }
    elsif (req.http.Accept-Encoding ~ "gzip") {
      set req.http.Accept-Encoding = "gzip";
    }
    else {
      # Unknown or deflate algorithm
      remove req.http.Accept-Encoding;
    }
  }

  // Let's have a little grace
  set req.grace = 30s;

  return (lookup);
}

 sub vcl_hash {
   if (req.http.Cookie) {
     set req.hash += req.http.Cookie;
   }
 }

 // Strip any cookies before an image/js/css is inserted into cache.
 sub vcl_fetch {
   if (req.url ~ "\.(png|gif|jpg|swf|css|js)$") {
     // This is for Varnish 2.0; replace obj with beresp if you're running
     // Varnish 2.1 or later.
     unset beresp.http.set-cookie;
   }
 }

 sub vcl_error {
   // Let's deliver a friendlier error page.
   // You can customize this as you wish.
   set obj.http.Content-Type = "text/html; charset=utf-8";
   synthetic {"
   <?xml version="1.0" encoding="utf-8"?>
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   <html>
     <head>
       <title>"} obj.status " " obj.response {"</title>
       <style type="text/css">
       #page {width: 400px; padding: 10px; margin: 20px auto; border: 1px solid black; background-color: #FFF;}
       p {margin-left:20px;}
       body {background-color: #DDD; margin: auto;}
       </style>
     </head>
     <body>
     <div id="page">
     <h1>Page Could Not Be Loaded</h1>
     <p>We're very sorry, but the page could not be loaded properly. This should be fixed very soon, and we apologize for any inconvenience.</p>
     <hr />     <h4>Debug Info:</h4>
     <pre>
 Status: "} obj.status {"
 Response: "} obj.response {"
 XID: "} req.xid {"
 </pre>
       <address><a href="http://www.varnish-cache.org/">Varnish</a></address>
       </div>
     </body>
    </html>
    "};
    return (deliver);
 }

3. Turn Ngnix to throw non-static request to Varnish:

  server {
    listen 62.xxx.xx.xx:80;
    server_name mysite.com www.mysite.com;
    rewrite ^(/manager/.*)$>https://$host$1>permanent;
    rewrite>^(/manager/.*)$>https://$host$1>permanent;
    location ~* ^/(webstat/|awstats|webmail/|myadmin/|manimg/) {
      proxy_pass http://62.xxx.xx.xx:8080;
      proxy_redirect http://mysite.com:8080/ /;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
    location / {
      proxy_pass http://62.xxx.xx.xx:8081;
      proxy_redirect http://mysite.com:8081/ /;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
    location ~* ^.+\.(jpg|jpeg|gif|png|svg|js|css|mp3|ogg|mpe?g|avi|zip|gz|bz2?|rar)$ {
      root /home/cross/data/www/mysite.com;
      access_log /home/httpd-logs/mysite.com.access.log;
      error_page 404 = @fallback;
    }
    location @fallback {
      proxy_pass http://62.109.14.92:8080;
      proxy_set_header Host $host;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Real-IP $remote_addr;
    }
  }

Step 5: Restart server

Ensure that Varnish is started - try to see 'top' command via SSH to find varnish process there.
Ensure that Varnish + Pressflow works well - execute varnishlog command via SSH and try to open http://mysite.com/, see if varnishlog show something line HTTP headers.

After all these step, I`ve got: http://blog.itcross.net/apache_nginx_varnish.jpg
As you see delay kept at the level.

These easy steps would launch Pressflow + Nginx + Varnish for your website and enlarge its performance. Enjoy!

Also, I`ll wonna try http://wiki.nginx.org/Drupal , but it is the next step. Thanks.

Additional links:

Comments

Fidelix’s picture

Awesome guide man.

However, i don't like that Apache is still being used.
I see no reason, as Nginx can run Drupal just as well...

cr0ss’s picture

Thank you Fidelix, I believe this guide would be helpful.

artemshymko.com