Linxfo’s Weblog

“Heil, mein Führer!”

Ruby on Rails Caching Tutorial

This tutorial is going to show everything you need to know to use Caching in your Rails applications,

Table of Contents

  1. Why for art thou caching?
  2. Configuration
  3. Page Caching
  4. Page caching with pagination
  5. Cleaning up your cache
  6. Sweeping up your mess
  7. Playing with Apache/Lighttpd
  8. Moving your cache
  9. Clearing out your whole/partial cache
  10. Advanced page caching techniques
  11. Testing your page caching
  12. Conclusion

Caching!

Caching, in the web application world, is the art of taking a processed web page (or part of a webpage), and storing it in a temporary location. If another user requests this same webpage, then we can serve up the cached version.

Loading up a cached webpage can not only save us from having to do ANY database queries, it can even allow us to serve up websites without touching our Ruby on Rails Server. Sounds kinda magical doesn’t it? Keep on reading for the good stuff.

Before we get our feet wet, there’s one small configuration step you need to take..

Configuration

There’s only one thing you’ll need to do to start playing with caching, and this is only needed if you’re in development mode. Look for the following line and change it to true in your /config/environments/development.rb:


config.action_controller.perform_caching = true

Normally you probably don’t want to bother with caching in development mode, but we want try it out already!

Page Caching

Page caching is the FASTEST Rails caching mechanism, so you should do it if at all possible. Where should you use page caching?

  • If your page is the same for all users.
  • If your page is available to the public, with no authentication needed.

If your app contains pages that meet these requirements, keep on reading. If it doesn’t, you probably should know how to use it anyways, so keep reading!

Say we have a blog page (Imagine that!) that doesn’t change very often. The controller code for our front page might look like this:

1
2
3
4
5 
class BlogController < ApplicationController
  def list
     Post.find(:all, :order => created_on desc, :limit => 10)
  end

As you can see, our List action queries the latest 10 blog posts, which we can then display on our webpage. If we wanted to use page caching to speed things up, we could go into our blog controller and do:

1
2
3
4
5
6
7 
class BlogController < ApplicationController
   caches_page :list
  
   def list
     Post.find(:all, :order => created_on desc, :limit => 10)
   end

The “caches_page” directive tells our application that next time the “list” action is requested, take the resulting html, and store it in a cached file.

If you ran this code using mongrel, the first time the page is viewed your /logs/development.log would look like this:

1
2
3
4
5
6 
Processing BlogController#list (for 127.0.0.1 at 2007-02-23 00:58:56) [GET]
 Parameters: {action=>list, controller=>blog}
SELECT * FROM posts ORDER BY created_on LIMIT 10
Rendering blog/list
Cached page: /blog/list.html (0.00000)
Completed in 0.18700 (5 reqs/sec) | Rendering: 0.10900 (58%) | DB: 0.00000 (0%) | 200 OK [http

See the line where it says "Cached page: /blog/list.html". This is telling you that the page was loaded, and the resulting html was stored in a file located at /public/blog/list.html. If you looked in this file you'd find plain html with no ruby code at all.

Subsequent requests to the same url will now hit this html file rather then reloading the page. As you can imagine, loading a static html page is much faster than loading and processing a interpreted programming language. Like 100 times faster!

However, it is very important to note that Loading Page Cached .html files does not invoke Rails at all! What this means is that if there is any content that is dynamic from user to user on the page, or the page is secure in some fashion, then you can't use page caching. Rather you'd probably want to use action or fragment caching, which I will cover in part 2 of this tutorial.

What if we then say in our model:


caches_page :show

Where do you think the cached page would get stored when we visited "/blog/show/5" to show a specific blog post?

The answer is /public/blog/show/5.html

Here are a few more examples of where page caches are stored.:

1
2
3
4
5 
http://localhost:3000/blog/list => /public/blog/list.html
http://localhost:3000/blog/edit/5 => /public/edit/5.html
http://localhost:3000/blog => /public/blog.html
http://localhost:3000/ => /public/index.html
http://localhost:3000/blog/list?page=2 => /public/blog/list.html

Hey, wait a minute, notice how above the first item is the same as the last item. Yup, page caching is going to ignore all additional parameters on your url.

But what if I want to cache my pagination pages?

Very interesting question, and a more interesting answer. In order to cache your different pages, you just have to create a differently formed url. So instead of linking "/blog/list?page=2", which wouldn't work because caching ignores additional parameters, we would want to link using "/blog/list/2", but instead of 2 being stored in params[:id], we want that 2 on the end to be params[:page].

We can make this configuration change in our /config/routes.rb

1
2
3
4
5 
map.connect blog/list/:page,
    :controller => blog,
    :action => list,
    :requirements => { :page => /\d+/},
    :page => nil

With this new route defined, we can now do:


<%= link_to Next Page, :controller => blog, :action => list, :page => 2 %>

the resulting url will be “/blog/list/2″. When we click this link two great things will happen:

  1. Rather than storing the 2 in params[:id], which is the default, the application will store the 2 as params[:page],
  2. The page will be cached as /public/blog/list/2.html

The moral of the story is; If you’re going to use page caching, make sure all the parameters you require are part of the URL, not after the question mark! Many thanks to Charlie Bowman for inspiration.

Cleaning up the cache

You must be wondering, “What happens if I add another blog post and then refresh /blog/list at this point?”

Absolutely NOTHING!!!

Well, not quite nothing. We would see the /blog/list.html cached file which was generated a minute ago, but it won’t contain our newest blog entry.

To remove this cached file so a new one can be generated we’ll need to expire the page. To expire the two pages we listed above, we would simply run:

1
2
3
4
5 
# This will remove /blog/list.html
expire_page(:controller => blog, :action => list)

# This will remove /blog/show/5.html
expire_page(:controller => blog, :action => show, :id => 5)

We could obviously go and add this to every place where we add/edit/remove a post, and paste in a bunch of expires, but there is a better way!

Sweepers

Sweepers are pieces of code that automatically delete old caches when the data on the cached page gets old. To do this, sweepers observe of one or more of your models. When a model is added/updated/removed the sweeper gets notified, and then runs those expire lines I listed above.

Sweepers can be created in your controllers directory, but I think they should be separated, which you can do by adding this line to your /config/environment.rb.

1
2
3
4
5 
Rails::Initializer.run do |config|
   # …
   config.load_paths += %W( #{RAILS_ROOT}/app/sweepers )
   # …
end

(don’t forget to restart your server after you do this)

With this code, we can create an /app/sweepers directory and start creating sweepers. So, lets jump right into it. /app/sweepers/blog_sweeper.rb might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 
class BlogSweeper < ActionController::Caching::Sweeper
  observe Post # This sweeper is going to keep an eye on the Post model

  # If our sweeper detects that a Post was created call this
  def after_create(post)
          expire_cache_for(post)
  end
  
  # If our sweeper detects that a Post was updated call this
  def after_update(post)
          expire_cache_for(post)
  end
  
  # If our sweeper detects that a Post was deleted call this
  def after_destroy(post)
          expire_cache_for(post)
  end
          
  private
  def expire_cache_for(record)
    # Expire the list page now that we posted a new blog entry
    expire_page(:controller => blog, :action => list)
    
    # Also expire the show page, incase we just edited a blog entry
    expire_page(:controller => blog, :action => show, :id => record.id)
  end
end

NOTE: We can call “after_save”, instead of “after_create” and “after_update” above, to dry out our code.

We then need to tell our controller when to invoke this sweeper, so in /app/controllers/BlogController.rb:

1
2
3
4 
class BlogController < ApplicationController
   caches_page :list, :show
   cache_sweeper :blog_sweeper, :only => [:create, :update, :destroy]

If we then try creating a new post we would see the following in our logs/development.log:

1
2 
Expired page: /blog/list.html (0.00000)
Expired page: /blog/show/3.html (0.00000)

That’s our sweeper at work!

Playing nice with Apache/Lighttpd

When deploying to production, many rails applications still use Apache as a front-end, and dynamic Ruby on Rails requests get forwarded to a Rails Server (Mongrel or Lighttpd). However, since we are actually pushing out pure html code when we do caching, we can tell Apache to check to see if the page being requested exists in static .html form. If it does, we can load the requested page without even touching our Ruby on Rails server!

Our httpd.conf might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 
<VirtualHost *:80>

  # Configure mongrel_cluster
  <Proxy balancer://blog_cluster>
    BalancerMember http://127.0.0.1:8030
  </Proxy>

  RewriteEngine On
  # Rewrite index to check for static
  RewriteRule ^/$ /index.html [QSA]

  # Rewrite to check for Rails cached page
  RewriteRule ^([^.]+)$ $1.html [QSA]

  # Redirect all non-static requests to cluster
  RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
  RewriteRule ^/(.*)$ balancer://blog_cluster%{REQUEST_URI} [P,QSA,L]

</VirtualHost>

In lighttpd you might have:

1
2
3 
server.modules = ( mod_rewrite, … )
url.rewrite += ( ^/$ => /index.html )
url.rewrite += ( ^([^.]+)$ => $1.html )

The proxy servers will then look for cached files in your /public directory. However, you may want to change the caching directory to keep things more separated. You’ll see why shortly.

Moving your Page Cache

First you’d want to add the following to your /config/environment.rb:


config.action_controller.page_cache_directory = RAILS_ROOT + /public/cache/

This tells Rails to publish all your cached files in the /public/cache directory. You would then want to change your Rewrite rules in your httpd.conf to be:

1
2
3
4
5 
  # Rewrite index to check for static
  RewriteRule ^/$ cache/index.html [QSA]

  # Rewrite to check for Rails cached page
  RewriteRule ^([^.]+)$ cache/$1.html [QSA]

Clearing out a partial/whole cache

When you start implementing page caching, you may find that when you add/edit/remove one model, almost all of your cached pages need to be expired. This could be the case if, for instance, all of your website pages had a list which showed the 10 most recent blog posts.

One alternative would be to just delete all your cached files. In order to do this you’ll first need to move your cache directory (as shown above). Then you might create a sweeper like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 
class BlogSweeper < ActionController::Caching::Sweeper
  observe Post

  def after_save(record)
    self.class::sweep
  end
  
  def after_destroy(record)
    self.class::sweep
  end
  
  def self.sweep
    cache_dir = ActionController::Base.page_cache_directory
    unless cache_dir == RAILS_ROOT+/public
      FileUtils.rm_r(Dir.glob(cache_dir+/*)) rescue Errno::ENOENT
      RAILS_DEFAULT_LOGGER.info(Cache directory ‘#{cache_dir}‘ fully sweeped.)
    end
  end
end

That FileUtils.rm_r simply deletes all the files in the cache, which is really all the expire_cache line does anyways. You could also do a partial cache purge by only deleting a cache subdirectory. If I just wanted to remove all the caches under /public/blog I could do:

1
2 
        cache_dir = ActionController::Base.page_cache_directory
        FileUtils.rm_r(Dir.glob(cache_dir+/blog/*)) rescue Errno::ENOENT

If calling these File Utilities feels too hackerish for you, Charlie Bowman wrote up the broomstick plugin which allows you to “expire_each_page” of a controller or action, with one simple call.

Needing something more advanced?

Page caching can get very complex with large websites. Here are a few notable advanced solutions:

Rick Olson (aka Technoweenie) wrote up a Referenced Page Caching Plugin which uses a database table to keep track of cached pages. Check out the Readme for examples.

Max Dunn wrote a great article on Advanced Page Caching where he shows you how he dealt with wiki pages using cookies to dynamically change cached pages based on user roles.

Lastly, there doesn’t seem to be any good way to page cache xml files, as far as I’ve seen. Mike Zornek wrote about his problems and figured out one way to do it. Manoel Lemos figured out a way to do it using action caching. We’ll cover action caching in the next tutorial.

How do I test my page caching?

There is no built in way to do this in rails. Luckily Damien Merenne created a swank plugin for page cache testing. Check it out!

Quoted from  railsenvy.com

March 30, 2008 Posted by linxfo | Ruby on Rails | | No Comments

A Flickr-based Introduction to Ruby on Rails 2.0

Installation and Basic Setup
The first thing you have to do is install the Rails 2.0 framework and create a basic application scaffold to verify that everything has been setup properly. If the Ruby language and RubyGems, the standard packaging system for Ruby libraries, are not already installed on your system, refer to the Ruby and RubyGems web sites for further installation information. Also, check out Pastie, a tool that checks if your applications based on Rails 1.x are ready to be migrated to the new version.

Once you have these ready to go, you can install Rails 2.0 using the same procedure as for the previous version of the framework. Then open a terminal and enter this command:


gem install rails --include-dependencies

You can also launch the gem command with explicit references to the required libraries and verify that it downloads the correct packages from the Internet:


$ sudo gem update actionmailer actionpack activerecord activesupport
$ sudo gem install activeresource
$ sudo gem update rails
$ ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [universal-darwin9.0]
$ gem -v
1.0.1
$ rails -v
Rails 2.0.2
$ gem list –local

*** LOCAL GEMS ***

actionmailer (2.0.2, 1.3.6, 1.3.3)
actionpack (2.0.2, 1.13.6, 1.13.3)
actionwebservice (1.2.6, 1.2.3)
activerecord (2.0.2, 1.15.6, 1.15.3)
activeresource (2.0.2)
activesupport (2.0.2, 1.4.4, 1.4.2)
rails (2.0.2, 1.2.6, 1.2.3)
… other libraries here …

As you can see, you can keep the previous version of Rails alongside with the new one, to facilitate the transition of existing applications built upon previous Rails versions. The above example has both Rails 2.0.2 and two previous versions of Rails 1.2. (The Ruby on Rails download page describes additional ways of installing it.)

To verify that everything is working correctly, you can generate a scaffold for a new web application with this command:

rails testapp cd testapp/ script/server Open your browser at the URL http://localhost:3000 to verify that you are using the latest version of Rails. You should see a welcome screen for your newly created Rails 2.0 application. If you don’t, check the RAILS_GEM_VERSION in the testapp/config/environment.rb file.

The RailTrackr Application
RailTrackr, the visually rich, web-based Flickr photo browser, will demonstrate some notable Rails 2.0 capabilities. You can launch the sample application now by downloading the source code attached to this article and launching it with the traditional script/server command. Since the application uses the Flickr APIs to load photos, you have to request an API key from the Flickr services site and type it into the flickr_helper.rb file bundled with the source code.

The application provides a way to navigate through Flickr users, their photosets, and the photos contained within them. It therefore defines three entities: FlickrUser, Photoset, and Photo. In the application domain, a FlickrUser may have many Photosets, and each Photoset may have many Photos. These will be the Ruby models for RailTrackr.

Quoted from www.devx.com

March 15, 2008 Posted by linxfo | Ruby on Rails | | No Comments

SafeErb for Rails 2

You might have noticed that the SafeErb plugin does not work in Rails 2 applications. That is because of old method signatures used in the plugin. The author has put up a blog post (in japanese) about a new version created by Aaron Bedra which points to this plugin installer (possibly replace http by svn):

./script/plugin install http://safe-erb.rubyforge.org/svn/plugins/safe_erb

The author has tested it with Rails 2.0.2 and it works fine. On my system however, it has problems with methods from the FormHelper (text_field and so on), most likely because of the output values in the value parameter. Does this happen on your system, as well? I hope to find a fix for that. Apart from that, the plugin works fine for Rails 2 applications.

 

Quoted from rorsecurity.info

March 15, 2008 Posted by linxfo | Ruby on Rails | | No Comments

InvalidAuthenticityToken for in_place_editing

There is a problem with InvalidAuthenticityToken errors that are raised in the methods for the in_place_editing plugin. This happens in Rails 2.0.2 (and possibly earlier versions). It’s because there is no authenticity_token sent at all. You can apply this patch until there is a new version out.

If you have something like this:

<%= in_place_editor(”title”, {:url => url_for(:action => “update_title” …)}) %>

the update_title method will throw an error. Apply the patch to make it work.

 

Quoted from rorsecurity.info

March 15, 2008 Posted by linxfo | Ruby on Rails | | No Comments

Thin : A fast and very simple Ruby web server

What

Thin is a Ruby web server that glues together 3 of the best Ruby libraries in web history:

  • the Mongrel parser, the root of Mongrel speed and security
  • Event Machine, a network I/O library with extremely high scalability, performance and stability
  • Rack, a minimal interface between webservers and Ruby frameworks

Which makes it, with all humility, the most secure, stable, fast and extensible Ruby web server bundled in an easy to use gem for your own pleasure.

Installation & Usage
Minimum Requirements include either Ruby 1.86 or 1.9. Love that last bit about 1.9.

sudo gem install thin

Using with Rails

After installing the Gem, a thin script should be in your path to easily start your Rails application.

cd to/your/rails/app
thin start    But Thin can also load Rack config file so you can use it with any
framework that supports Rack. Even your own that is, like, soooo much
better then Rails, rly!

test.ru

app = proc do |env|
  [
    200,          # Status code
    {             # Response headers
      'Content-Type' => 'text/html',
      'Content-Length' => '2',
    },
    ['hi']        # Response body
  ]
end

# You can install Rack middlewares
# to do some crazy stuff like logging,
# filtering, auth or build your own.
use Rack::CommonLogger

run app
thin start -r test.ru  See Rack doc for more.

Deploying

Deploying a cluster of Thins is super easy. Just specify the number of servers you want to launch.

thin start --servers 3

You can also install Thin as a runlevel script (under /etc/init.d/thin) that will start all your servers after boot.

sudo thin install

and setup a config file for each app you want to start:

thin config -C /etc/thin/myapp.yml -c /var/...

Run thin -h to get all options.


Behind Nginx

Check out this sample Nginx config file to proxy requests to a Thin backend.

then start your Thin cluster like this:

thin start -s3 -p 5000

You can also setup a Thin config file and use it to control your cluster:

thin config -C myapp.yml -s3 -p 5000
thin start -C myapp.yml           ----------

To connect to Nginx using UNIX domain sockets edit the upstream block

in your nginx config file:

nginx.conf

      upstream  backend {
   server   unix:/tmp/thin.0.sock;
   server   unix:/tmp/thin.1.sock;
   server   unix:/tmp/thin.2.sock;
}

and start your cluster like this:

    thin start -s3 --socket /tmp/thin.sock       --------------   Quoted from  code.macournoyer.com

March 10, 2008 Posted by linxfo | Ruby on Rails | | No Comments

iPhone on Rails

Creating an iPhone optimised version of your Rails site using iUI and Rails 2

With Rails 2 you can create a mime type specifically for the iPhone and then use that format in a respond_to block (along with views such as index.iphone.erb).

Before you start – iPhoney

iPhoney is an indispensable Mac-only tool for aiding the development of an iPhone specific site.

Looking for a way to see how your web creations will look on iPhone? Look no further. iPhoney gives you a pixel-accurate web browsing environment—powered by Safari—that you can use when developing web sites for iPhone. It’s the perfect 320 by 480-pixel canvas for your iPhone development. And it’s free. iPhoney is not an iPhone simulator but instead is designed for web developers who want to create 320 by 480 (or 480 by 320) websites for use with iPhone. It gives you a canvas on which to test the visual quality of your designs.

Ensure iPhoney’s user agent is set to iPhone User Agent in the menu.

iPhone mime type

Create an iPhone mime type alias using Rails 2 initializers.

config/initializers/mime_types

Mime::Type.register_alias "text/html", :iphone

Detecting iPhone user agents

Apple recommends that rather than redirecting iPhone users to an iPhone-optimised version of your site you should instead show the original site with a link to the alternative.

This can be achieved via user agent sniffing; looking for Mobile Safari (as Apple suggests), rather that iPhone or iPod touch, to allow for future device support.

Adding a helper method to application_helper.rb allows a notification message to be shown for only iPhone users (try accessing www.trawlr.com from an iPhone).

app/helpers/application_helper.rb

# Request from an iPhone or iPod touch? (Mobile Safari user agent)
def iphone_user_agent?
  request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(Mobile\/.+Safari)/]
end

In your view, show a message for iPhone user agents directing them to the iPhone version.

<% if iphone_user_agent? # Show message for iPhone users -%>
<div class="message">
    <p>Using an iPhone? <a href="http://iphone.trawlr.com/">Use the optimised version</a>.</p>
</div>
<% end -%>

iPhone subdomain

Instead of forcing users straight to our iPhone version, we offer them the option by using a separate subdomain (iphone.trawlr.com) with a link back to the regular site if they wish. When developing locally I modified my /etc/hosts file as follows so that I could use http://iphone.localhost.com:3000/.

/etc/hosts

127.0.0.1 iphone.localhost.com   You may need to flush the DNS cache after making the changes.  sudo dscacheutil -flushcache

Adjust format for iPhone

I chose to require login for all requests to the iPhone version of the site.

class ApplicationController < ActionController::Base
    before_filter :adjust_format_for_iphone
    before_filter :iphone_login_required

private

  # Set iPhone format if request to iphone.trawlr.com
  def adjust_format_for_iphone
    request.format = :iphone if iphone_request?
  end

  # Force all iPhone users to login
  def iphone_login_required
    if iphone_request?
      redirect_to login_path unless logged_in?
    end
  end

  # Return true for requests to iphone.trawlr.com
  def iphone_request?
    return (request.subdomains.first == "iphone" || params[:format] == “iphone”)
  end
end

Note that sessions_controller.rb (handles login) requires skip_before_filter :iphone_login_required.

Using iUI and creating iPhone views

The iUI framework, based on Joe Hewitt’s iPhone navigation work, hugely simplifies iPhone web development. All you need to do is include the iUI JavaScript and CSS files along with included images and create your views in a particular structure to have native iPhone behaviour such as sliding menus and AJAX page loading.

Rails 2 makes it trivial to create different views depending upon the format, including layouts. Our iPhone layout includes a few specifics for iUI and a viewport meta tag for the device.

app/views/layouts/application.iphone.erb

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <meta id="viewport" name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
    <title><%= @page_title -%></title>
  <%= stylesheet_link_tag 'iui' %>
  <%= javascript_include_tag 'iui' %>
</head>
<body>
    <div class="toolbar">
        <h1 id="pageTitle"></h1>
        <a id="backButton" class="button" href="#"></a>
    </div>

    <%= yield %>
</body>

When creating your iPhone views you should follow the iUI style guide, an example page is given below. Standard hyperlinks are loaded using AJAX and slide into view, navigating back is handled by iUI. Links may be prefixed with target="_self" to replace the entire page or target="_replace" to replace the element with the response (using AJAX).

index.iphone.erb

————

<ul title="Home" selected="true">
    <li><%= link_to 'Example action', example_path %></li>
    <li><%= link_to 'Logout', logout_path, :method => :delete, :target => '_self' %></li>
</ul>

———-

show.iphone.erb ———-  <div class=”panel” title=”Example” selected=”true”>
    <h2>Example Content</h2>
    <p>Here’s some content</p>
</div> ——— It’s important to remember that iUI will load content using AJAX, thus you only need to render a layout (such as application.iphone.erb) for the first request or page of your iPhone site. All following requests should use render :layout => false (unless loaded into a new page with target="_replace"). If you experience any wierd rendering issues it’ll most likely be due to this irregularity.  respond_to do |format|
    format.iphone do  # action.iphone.erb
      render :layout => false
    end
end  ————–

References

The following resources on the new Rails 2 iPhone format ability and iUI library were extremely helpful; the documentation from Apple not so much!

  • http://developer.apple.com/iphone/
  • http://www.railspikes.com/2007/11/8/iphone-subdomains-with-rails
  • http://blog.nicksieger.com/articles/2007/09/18/railsconf-europe-david-heinemeier-hansson
  • http://www.joehewitt.com/blog/introducing_iui.php
  • http://code.google.com/p/iui/
 ------------------------   Quoted from slashdotdash.net

March 8, 2008 Posted by linxfo | Ruby on Rails | | No Comments

Monitoring nginx Server Statistics With rrdtool

This script is very easy to install and configure. You can use following steps to get pretty stats graph for your nginx-powered server:

  • Modify your nginx config file and add following location to it:
http {

server {
listen SOME.IP.ADD.RESS;

location /nginx_status {
stub_status on;
access_log   off;
allow SOME.IP.ADD.RESS;
deny all;
}

}

}
 * Test your config file with following command:
 # /your/installation/sbin/nginx -t
2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf syntax is ok
2006/04/29 04:24:36 [info] 31676#0: the configuration file /opt/nginx/conf/nginx.conf was tested successfully
#
If you will get error about stub_status directive, check your nginx - it should be configured with —-with-http_stub_status_module option.

  • If your configuration is OK, you can restart nginx and test it:
  •  # GET http://your-domain.com/nginx_status
    Active connections: 1492
    server accepts handled requests
    2124355 2124355 8278635
    Reading: 6 Writing: 405 Waiting: 1081
     Download  perl script: rrd_nginx.pl and make it executable with
    # chmod +x rrd_nginx.pl
     Change settings in rrd_nginx.pl to let script know where it will save rrd-base and images:
     #!/usr/bin/perl
    use RRDs;
    use LWP::UserAgent;

    # define location of rrdtool databases
    my $rrd = ‘/opt/rrd’;
    # define location of images
    my $img = ‘/opt/rrd/html’;
    # define your nginx stats URL
    my $URL = “http://your-domain.com/nginx_status”;

     Last step is to insert following string to /etc/crontab file and to restart cron daemon:
    * *     * * *   root    /some/path/rrd_nginx.pl  When all preparations will be finished, you get  images in your $img directory: ———————  Quoted from blog.kovyrin.net

    March 8, 2008 Posted by linxfo | Nginx | | No Comments

    Nginx HTTP(S) Reverse Proxy/Web Server

    This post with list of typical nginx configurations and example configuration snippets for these configurations.

    All sample configuration files are tested on up to date version of nginx, which has been compiled and installed with following commands:

    # ./configure –prefix=/usr/local/nginx –with-http_ssl_module
    # make
    # make install

    Using nginx as web server with PHP support

    If you need to use nginx with PHP, you can setup PHP as FastCGI and let nginx to forward all PHP queries to some FastCGI port (tcp/socket). To use this configuration you need to start PHP as FastCGI using some third party software like spawn-fcgi from lighttpd

    To enable PHP support, you need to add special location section to your config file:

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
    fastcgi_pass   127.0.0.1:12345;
    fastcgi_index  index.php;

    fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
    fastcgi_param  QUERY_STRING     $query_string;
    fastcgi_param  REQUEST_METHOD   $request_method;
    fastcgi_param  CONTENT_TYPE     $content_type;
    fastcgi_param  CONTENT_LENGTH   $content_length;
    }

    ——————-
    Using nginx as web server with SSI support

    Server-Side Includes (aka SSI) is another interesting feature of nginx. As for now, following ssi instructions are supported: config, echo, if, include, set.

    SSI support can be anabled by single line configuration command in your config file:

    location / {
    ssi  on;

    }
    Using nginx as https-enabled web server

    You need https-access to your Nginx-powered site? No problems! Nginx supports https and can be used to implement secured web-server with SSLv2, SSLv3 or TLSv1.

    To enable https-support you should have certificate and key files. How to obtain them, you can read in SSL FAQ. When you will obtain them, you can enable ssl-module:

    server {
    listen               443;
    ssl                  on;
    ssl_certificate      /usr/local/nginx/conf/cert.pem;
    ssl_certificate_key  /usr/local/nginx/conf/cert.key;
    keepalive_timeout    70;

    }
    Using nginx as reverse-proxy server before some another web-server

    If you have some large web-site and you have noticed, that your Apache can not handle more load, you can put nginx before your primary web-server to use it as light reverse-proxy and as web-server to handle requests to static files.

    Thanks to nginx flexibility, you can pass any types of requests to backend server by using location sections (all files, only dynamic content requests or some specific locations in your web-server tree):

    location / {
    proxy_pass        http://localhost:8000/;
    proxy_set_header  X-Real-IP  $remote_addr;
    }
    Using nginx for virtual hosting platforms

    One of the interesting use cases for Nginx is virtual hosting platform because it meets all requirements for good hosting server: it is efficient, it supports all popular virtual hosting methods and it has very good internal structure, so it can be easily extended in for any specific areas.

    As for now, it is being used by many hosting companies as reverse proxy and I am using it on my free hosting service with millions unique visitors per day.

    If you vant to try virtual hosting feature, you can create additional server sections in your config file (first section will be default):

    http {
    server {
    listen  192.168.10.1;
    listen  192.168.10.1:8000;

    server_name   one.example.com  www.one.example.com;

    }

    server {
    listen  192.168.10.1;
    listen  192.168.10.2:8000;
    listen  9000;

    server_name   two.example.com  www.two.example.com
    three.example.com  www.three.example.com;

    }

    server {
    listen  9000;

    server_name   four.example.com  www.four.example.com;

    }
    }

     Quoted from
    This post with list of typical nginx configurations and example configuration snippets for these configurations.

    All sample configuration files are tested on up to date version of nginx, which has been compiled and installed with following commands:

    # ./configure –prefix=/usr/local/nginx –with-http_ssl_module
    # make
    # make install

    Using nginx as web server with PHP support

    If you need to use nginx with PHP, you can setup PHP as FastCGI and let nginx to forward all PHP queries to some FastCGI port (tcp/socket). To use this configuration you need to start PHP as FastCGI using some third party software like spawn-fcgi from lighttpd

    To enable PHP support, you need to add special location section to your config file:

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {
    fastcgi_pass   127.0.0.1:12345;
    fastcgi_index  index.php;

    fastcgi_param  SCRIPT_FILENAME  /usr/local/nginx/html$fastcgi_script_name;
    fastcgi_param  QUERY_STRING     $query_string;
    fastcgi_param  REQUEST_METHOD   $request_method;
    fastcgi_param  CONTENT_TYPE     $content_type;
    fastcgi_param  CONTENT_LENGTH   $content_length;
    }

    ——————-
    Using nginx as web server with SSI support

    Server-Side Includes (aka SSI) is another interesting feature of nginx. As for now, following ssi instructions are supported: config, echo, if, include, set.

    SSI support can be anabled by single line configuration command in your config file:

    location / {
    ssi  on;

    }
    Using nginx as https-enabled web server

    You need https-access to your Nginx-powered site? No problems! Nginx supports https and can be used to implement secured web-server with SSLv2, SSLv3 or TLSv1.

    To enable https-support you should have certificate and key files. How to obtain them, you can read in SSL FAQ. When you will obtain them, you can enable ssl-module:

    server {
    listen               443;
    ssl                  on;
    ssl_certificate      /usr/local/nginx/conf/cert.pem;
    ssl_certificate_key  /usr/local/nginx/conf/cert.key;
    keepalive_timeout    70;

    }
    Using nginx as reverse-proxy server before some another web-server

    If you have some large web-site and you have noticed, that your Apache can not handle more load, you can put nginx before your primary web-server to use it as light reverse-proxy and as web-server to handle requests to static files.

    Thanks to nginx flexibility, you can pass any types of requests to backend server by using location sections (all files, only dynamic content requests or some specific locations in your web-server tree):

    location / {
    proxy_pass        http://localhost:8000/;
    proxy_set_header  X-Real-IP  $remote_addr;
    }
    Using nginx for virtual hosting platforms

    One of the interesting use cases for Nginx is virtual hosting platform because it meets all requirements for good hosting server: it is efficient, it supports all popular virtual hosting methods and it has very good internal structure, so it can be easily extended in for any specific areas.

    As for now, it is being used by many hosting companies as reverse proxy and I am using it on my free hosting service with millions unique visitors per day.

    If you vant to try virtual hosting feature, you can create additional server sections in your config file (first section will be default):

    http {
    server {
    listen  192.168.10.1;
    listen  192.168.10.1:8000;

    server_name   one.example.com  www.one.example.com;

    }

    server {
    listen  192.168.10.1;
    listen  192.168.10.2:8000;
    listen  9000;

    server_name   two.example.com  www.two.example.com
    three.example.com  www.three.example.com;

    }

    server {
    listen  9000;

    server_name   four.example.com  www.four.example.com;

    }

    )
     Quoted from blog.kovyrin.net

    March 8, 2008 Posted by linxfo | Nginx | | No Comments

    HOWTO: Install WordPress on Nginx

    Apache is a very well-establish web server that can handle just about any situation. Unfortunately, that flexibility comes at the cost of size and relatively high demands on server resources. Nginx (“engine x”) is a lightweight web server/reverse proxy that is very efficient and perfect for hosting WordPress. Read on to see how that can be done…

    Step One: FastCGI

    First off, Nginx does not provide FastCGI for you (FastCGI is what your web server uses to interact with WordPress’s PHP code), so you’ve got to have a way to spawn your own FastCGI processes. My preferred method is to use the spawn-fcgi program provided by the web server lighttpd. You can use PHP’s built-in FastCGI manager php-cgi to do the same thing, but it’s not as straight-forward. Plus, if you learn how to use spawn-fcgi, you can easily adapt it for use with other web applications requiring FastCGI.

    Install spawn-fcgi

    To download and install spawn-fcgi, run the following commands. Don’t worry, all of the building happens in your current directory…nothing else will be installed on your machine.

    $ wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.bz2
    $ tar -xvjf lighttpd-1.4.18.tar.bz2
    $ cd lighttpd-1.4.18/
    $ ./configure
    $ make
    $ sudo cp src/spawn-fcgi /usr/bin/spawn-fcgi  After spawn-fcgi has been copied to the desired location, you can safely remove the build directory and original source file:    $ cd ..
    $ rm -rf lighttpd-1.4.18/
    $ rm lighttpd-1.4.18.tar.bz2

    Run spawn-fcgi

    This part will be fairly distribution-specific, but I’ll provide the basic command that you’ll need. What you want to do is find a way to run this command as part of your init scripts so the processes will be spawned automatically when you reboot your server.

    /usr/bin/spawn-fcgi -f /usr/bin/php-cgi -a 127.0.0.1 -p 53217 -P /var/run/fastcgi-php.pid

    • -f → the filename of the fcgi-application; in our case we want “php-cgi”, which is provided by your distribution’s PHP package. If you don’t know where to find it, try running which php-cgi on the command line.
    • -a → the IP address to bind the processes to; in our case we want the localhost
    • -p → the port number to bind the processes to; pick whatever you want that won’t cause a conflict (technically it would be best to pick a random number between 49152 and 65535), just make sure to remember the number and use that same port for your Nginx configuration file later on
    • -P → the location where to save the process id file; you can use this file to easily kill the processes later

    For better security, you can also spawn the processes as a non-privileged user by specifying the user/group with the -u and -g flags respectively. For more information on all the available options, run spawn-fcgi -h on the command line.

    If you’re interested in seeing the complete init script that I wrote for use with Arch Linux, you can download it here: fastcgi-php

    Step Two: Complete 83.33% of the Famous 5-Minute Install

    Next you should download the WordPress files and extract them to their final location on your server. Simply follow steps 1–5 of the Famous 5-Minute Install (the 6th and final step requires that your web server be up and running properly, so we’ll do it later). This guide will assume that you extracted the WordPress core files here: /srv/www/nginx/domain.com/

    Step Three: Nginx Configuration

    To get the web server up and running properly, the file you need to edit is called “nginx.conf” and is installed in different places depending on your Linux distribution. If you install Nginx from source, the default location is /usr/local/nginx/conf/nginx.conf, however yours may be somewhere else.

    Once you find that file, open it with your favorite text editor and add a server declaration that looks something like this (I’ll cover what each part means after posting the code):

    server {
        listen       12.34.56.78:80;  # your server’s public IP address
        server_name  domain.com;      # your domain name
    
        location / {
            root   /srv/www/nginx/domain.com;  # absolute path to your WordPress installation
            index  index.php index.html index.htm;
    
            # this serves static files that exist without running other rewrite tests
            if (-f $request_filename) {
                expires 30d;
                break;
            }
    
            # this sends all non-existing file or directory requests to index.php
            if (!-e $request_filename) {
                rewrite ^(.+)$ /index.php?q=$1 last;
            }
        }
    
        location ~ \.php$ {
            fastcgi_pass   localhost:53217;  # port where FastCGI processes were spawned
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME    /srv/www/nginx/domain.com$fastcgi_script_name;  # same path as above
    
            fastcgi_param  QUERY_STRING       $query_string;
            fastcgi_param  REQUEST_METHOD     $request_method;
            fastcgi_param  CONTENT_TYPE       $content_type;
            fastcgi_param  CONTENT_LENGTH     $content_length;
    
            fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
            fastcgi_param  REQUEST_URI        $request_uri;
            fastcgi_param  DOCUMENT_URI       $document_uri;
            fastcgi_param  DOCUMENT_ROOT      $document_root;
            fastcgi_param  SERVER_PROTOCOL    $server_protocol;
    
            fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
            fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
    
            fastcgi_param  REMOTE_ADDR        $remote_addr;
            fastcgi_param  REMOTE_PORT        $remote_port;
            fastcgi_param  SERVER_ADDR        $server_addr;
            fastcgi_param  SERVER_PORT        $server_port;
            fastcgi_param  SERVER_NAME        $server_name;
    
            # required if PHP was built with –enable-force-cgi-redirect
            fastcgi_param  REDIRECT_STATUS    200;
        } }

    You will need to edit all of the highlighted sections above using your own information. The first part is merely the server declaration where you define what your server’s publicly available IP address is and what domain name that address is associated with.

    Next we add to that some default settings for the root location. The key part here is that WordPress uses the “Front Controller” design pattern, meaning that any request for a file that does not exist on the server should be handled by the main index.php file. To do this, we need an appropriate set of rewrite rules pointing to the proper path of our installation.

    Last, we add one more location block that tells Nginx to dynamically forward PHP requests to the FastCGI processes we spawned earlier. That’s it!

    Step Four: Finishing Up

    Everything should be good to go…all you need to do now is start your Nginx server process (another distribution specific command), then complete the 6th step of the Famous 5-Minute Install and you should have WordPress up and running on Nginx!

    
    
    
    
    

    Quoted from elasticdog.com

    March 8, 2008 Posted by linxfo | Nginx | | No Comments

    Ruby : Timeout code execution

    Just a small tip, if you wish to ensure a snippet of Ruby code doesn’t run for too long you can use the timeout function. You might want to do this when making a request to a remote server with net/http for example.

    timeout.rb

    A way of performing a potentially long-running operation in a thread, and terminating it‘s execution if it hasn‘t finished within fixed amount of time.

    Here’s a quick example using the excellent rFeedParser (Universal Feed Parser in Ruby) to fetch an RSS feed.

    require 'timeout'
    require 'zlib'
    require 'rubygems'
    require 'rfeedparser'
    
    fp = nil
    begin
      # Don't take longer than 20 seconds to retrieve & parse an RSS feed
      Timeout::timeout(20) do
        fp = FeedParser.parse("http://feeds.feedburner.com/slashdotdash")
      end
    rescue Timeout::Error
      # Too slow!! end   Quoted  from slashdotdash.net

    March 7, 2008 Posted by linxfo | Ruby on Rails | | No Comments