Rails URLs always try to open non-existent files

The lighttpd config file is set up like this…

Rails url: //host/controller/method/id
Lighttpd tries to open the file ‘controller/method/id’ from the document
root.
Of course this doesn’t work and generates an error 404
This gets caught with: server.error-handler-404 = “/dispatch.fcgi”
Which turns the request into “/dispatch.fcgi”
That gets caught by: fastcgi.server = (".fcgi" =>…
And it finally ends up in Rails.

Apache is doing similar work with:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]

Why aren’t the servers setup to mount the app someplace like ‘app’ and
avoid all of this indirection? You can use fastcgi.server = ("/app" =>
to route all URLs starting with ‘app’ into Rails.

Other than letting you use ‘//host/controller/method/id’ instead of
‘//host/app/controller/method/id’ is there some other advantage to
trying to open the file first?


Jon S.
[email protected]

Rails url: //host/controller/method/id
Lighttpd tries to open the file ‘controller/method/id’ from the
document root.
Of course this doesn’t work and generates an error 404
This gets caught with: server.error-handler-404 = “/dispatch.fcgi”
Which turns the request into “/dispatch.fcgi”
That gets caught by: fastcgi.server = (".fcgi" =>…
And it finally ends up in Rails.

And how long does this take? Measure it.

My machine is a PowerBook G4 (1.67Ghz, 5,400RM laptop HD using HFS+)
running Lighttpd and setting the 404 handler to a static HTML file.
The file is 36kb so the network transfer isn’t an issue.

apachebench -n 5000 -c 5 gives me:
Requests per second: 1356.48 [#/sec] (mean)
For a direct request:
Requests per second: 1566.91 [#/sec] (mean)

As for a network drive:
Requests per second: 119.37 [#/sec] (mean)
vs
Requests per second: 173.03 [#/sec] (mean)

This is for the same machine above accessing a directory mounted via
AFP over an 802.11g wireless connection. Hardly fast. The remote
server has a standard 80GB 7,200RPM hard drive using ReiserFS. Unless
you’re Yahoo or someone you won’t need to care, and I’d assume that
anyone actually running an app will use a decent fileserver with fast
interconnects and mount drives with NFS.

The bottom line is that the redirection doesn’t take any time worth
caring about.

Why aren’t the servers setup to mount the app someplace like ‘app’ and
avoid all of this indirection? You can use fastcgi.server = ("/app" =>
to route all URLs starting with ‘app’ into Rails.

Yes, you can, but…

Other than letting you use ‘//host/controller/method/id’ instead of
‘//host/app/controller/method/id’ is there some other advantage to
trying to open the file first?

Page caching. Typo caches all blog posts as a whole action, so it’s
saved as a file. If you get slashdotted the majority of page requests
go like this:
Lighttpd finds file, sends file
Rather than
Lighttpd forwards request to Rails app
Rails app finds file
Rails add sends file to Lighttpd
Lighttpd sends file to client.

This is Rails serving a static .rhtml file, same machine as above,
served from localhost:
Requests per second: 5.52 [#/sec] (mean)

If you want speed keep it outside of Rails. If you’re serving dynamic
pages the little bit of indirection costs very little compared to DB
queries and starting up a Rails app.

On 1/14/06, Phillip H. [email protected] wrote:

saved as a file. If you get slashdotted the majority of page requests
Requests per second: 5.52 [#/sec] (mean)
That’s the answer I was looking for, it’s how page caching is
implemented. I hadn’t discovered page caching in Rails yet so I
couldn’t explain the check for the non-existent files. Now that I’ve
ready up on page caching it makes perfect sense.


Jon S.
[email protected]

On 1/13/06, Ezra Z. [email protected] wrote:

Jon-

    Rails does this so that it can serve static files like stylesheets

and images and cached pages as well, without going through rails.
Page caching wouldn’t work ar be anywhere near as fast if it had to
go through rails first. The amount of time it takes for a webserver
to see if a file exists is infinitesimal and isn’t really an issue to
worry about.

You could leave your public directory alone, all of the URLs for
images, stylesheets, etc would stay the same. Only the URLs for Rails
generated pages would change, instead of //host/controller/id it would
be //host/app/controller/id. The the server would key off /app.

Right now the Rails names space in mixed into the public namespace.
The only way to make things work is to first check for existence in
the public namespace and then if it isn’t there use the Rails
namespace.

So far the only two advantages to this I see are:

  1. you don’t have to add ‘/app’ to the URL
  2. you can replace a Rails generated page by placing a static one in
    front of it in the public hierarchy.

Checking for non-existence of files doesn’t take a lot of time but it
is not free on SMP systems or if the file system is on a network
mount.


Jon S.
[email protected]

On Jan 13, 2006, at 4:58 PM, Jon S. wrote:

trying to open the file first?

Jon S.

Jon-

Rails does this so that it can serve static files like stylesheets

and images and cached pages as well, without going through rails.
Page caching wouldn’t work ar be anywhere near as fast if it had to
go through rails first. The amount of time it takes for a webserver
to see if a file exists is infinitesimal and isn’t really an issue to
worry about.

Cheers-
-Ezra Z.
Yakima Herald-Republic
WebMaster
http://yakimaherald.com
509-577-7732
[email protected]