RESTful page caching met Nginx

Geplaatst door Matthijs Langenberg vr, 08 feb 2008 16:17:00 GMT

Op onze interne testomgeving bij Newminds maken we gebruik van Nginx als frontend webserver. Elke binnenkomende request wordt door Nginx doorgestuurd naar een mongrel proces. Onlangs heb ik rails page caching ingeschakeld en in dit artikel wil ik mijn ervaringen graag met je delen.

In dit artikel zal ik beschrijven wat er in het ‘server’ blok van de nginx configuratie gezet moet worden om statische files (die door rails worden gegenereerd) direct vanaf het bestandsysteem te versturen. Hierbij ga ik er vanuit dat je bekend bent met de configuratie files die nginx gebruikt, als je hier niet bekend mee bent zou je Ezra Zygmuntowicz’s voorbeeld Nginx configuratie kunnen bekijken.

Lees verder...

Tags ,  | geen reacties

Enabling RESTful page caching with Nginx

Geplaatst door Matthijs Langenberg do, 07 feb 2008 10:02:00 GMT

At Newminds our internal test environment is running a Nginx webserver as a frontend proxying every request to a mongrel server. Recently, I wanted to setup page caching to increase the performance of our service. So, let me share my experience with you.

I’ll be describing what to put in the ‘server’ block of the nginx configuration. If you aren’t familiar with a nginx configuration file yet, you can checkout Ezra Zygmuntowicz’s Nginx example configuration.

Let’s start simple:

server {
  location / {
    proxy_pass http://mongrel
  }
}

This will proxy all request to the mongrel server, which is fine but doesn’t serve any static content (cached) content of course. In order to do that, we will need to extend the above block a little bit.


server {
  # specify document root
  # see: http://wiki.codemongers.com/NginxHttpCoreModule#root
  root /home/user/apps/my_app/current/public;

  location / {
    # if the file exists as a static file serve it directly
    if (-f $request_filename) {
      break;
    }

    # check for index.html for directory index
    # if it's there on the filesystem then rewrite
    # the url to add /index.html to the end of it
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }

    # add .html to the end of the url and check the filesystem
    # if it exists, serve it directly, else hit mongrel
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }

    if (-f $request_filename) {
      proxy_pass http://mongrel;
      break;
    }
}

Great! This will serve all our page cache as static content making the application blazing fast! But there is one flaw: a GET /fruits/23 will serve public/fruits/23.html from the filesystem. That works as intended, but when someone wants to update this little fruit he will send a PUT /fruits/23. When that happens, Nginx checks the filesystem on an existing file at public/fruits/23.html, this check will return true and breaks. It will never hit mongrel. In fact Nginx even returns a 405 Method Not Allowed HTTP status code, because Nginx only knows how to GET a file, not how to PUT one.

This means we need to modify the configuration so Nginx only serves the static content if the HTTP request method is GET or HEAD. This will lead us to the final configuration block, which passes all requests except GET or HEAD immediately to mongrel.


server {
  # specify document root
  # see: http://wiki.codemongers.com/NginxHttpCoreModule#root
  root /home/user/apps/my_app/current/public;

  location / {
    # only try to serve a static file if the request method is GET or HEAD
    # if it's anything else (POST for example) hit mongrel.
    if ($request_method !~ "GET|HEAD") {
      proxy_pass http://mongrel;
      break;
    }

    # if the file exists as a static file serve it directly
    if (-f $request_filename) {
      break;
    }

    # check for index.html for directory index
    # if it's there on the filesystem then rewrite
    # the url to add /index.html to the end of it
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }

    # add .html to the end of the url and check the filesystem
    # if it exists, serve it directly, else hit mongrel
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }

    if (-f $request_filename) {
      proxy_pass http://mongrel;
      break;
    }
}

Let me know if this post was useful for you.

Geplaatst in  | Tags ,  | 1 reactie