Nginx reverse proxy + mongrel and fork

Hi all,

I originally posted this to the rails deployment list, but then I
noticed the nginx forum, and thought it would be better suited here.

I’m trying to kick off simple (yet long running) background processes
from within my rails app. I’m using Tom Anderson’s spawn plugin
http://rubyforge.org/projects/spawn/ to fork a child process and unhook
the active record DB connections to keep rails happy. Anyway,
everything works great when I hit a mongrel process directly
(http://myapp:3000/controller/action). The action quickly executes, the
results are returned to my browser, and the child process takes its time
doing the heavy lifting. I can hit that mongrel process again and
verify that it’s free to serve up another request.

Life is good-- that is until, I bring nginx into the mix. With nginx
proxying to the upstream :3000 mongrel, the response isn’t immediately
returned to my browser. Instead, the rails log file shows that the
request is finished, but my browser continues to spin, waiting for the
response. If I stop the request, I can load an alternate action to
verify that the lone mongrel is free to serve another request.

Has anyone had success with nginx, mongrel, and child processes? I just
installed pen to balance the single mongrel, and it worked as expected.

My dev box is intel mac, ruby 1.8.6, mongrel 1.1.2, nginx 0.5.34 (tried
with same results on 0.5.32.)

Thanks!

Hi,

On Don 20.12.2007 22:07, Nicky Be wrote:

Hi all,

I originally posted this to the rails deployment list, but then I
noticed the nginx forum, and thought it would be better suited here.

[snipp]

Life is good-- that is until, I bring nginx into the mix. With nginx
proxying to the upstream :3000 mongrel, the response isn’t immediately
returned to my browser. Instead, the rails log file shows that the
request is finished, but my browser continues to spin, waiting for the
response. If I stop the request, I can load an alternate action to
verify that the lone mongrel is free to serve another request.

1.) what do you mean with ‘immediately’?
2.) do you get the answer?
3.) is there a entry in the error log?
4.) please can you add some timing vars in your logs
http://wiki.codemongers.com/NginxHttpLogModule#log_format
=> request_time
http://wiki.codemongers.com/NginxHttpUpstreamModule
=> $upstream_response_time

Cheers

Aleks

On Dec 22, 2007, at 11:10 AM, Nicky Be wrote:

Eventually, nginx does return the response: here are some abbreviated
The first line is requesting the long running action (which calls
upstream: “http://127.0.0.1:3000/admin/categories/refresh_solr/62”,
host: “localhost”, referrer:
http://localhost/admin/categories/products

Thanks!

I’ve seen this same problem with nginx and forking in mongrel/rails.
In fact I’ve seen the same thing with apache as well. The answer is
do not fork in a rails app ever. It will just not work and will
lead to subtle bugs exactly like what you are seeing. Give yourself a
break and do not fork a rails app.

If you need a way to kick off a long task then use this:

http://codeforpeople.rubyforge.org/svn/bj/trunk/README

Cheers-

Ezra Z. wrote:

In fact I’ve seen the same thing with apache as well. The answer is
do not fork in a rails app ever. It will just not work and will
lead to subtle bugs exactly like what you are seeing. Give yourself a
break and do not fork a rails app.

Thanks for the reply-- I’ll look into Bj, although I was hoping to avoid
going down that path. If you could, could you elaborate on why forking
is a bad idea? From what I’ve read, active record db connections seemed
to be the culprit. It seems odd to me that my app works fine if I don’t
front it with nginx, or if I use an alternative reverse proxy (pen.)

Thanks Ezra.

Aleksandar L. wrote:

1.) what do you mean with ‘immediately’?

The rails log confirms that the mongrel (upstream) process has finished.
At this point, nginx should return the response immediately, but it
doesn’t.

2.) do you get the answer?

Eventually, nginx does return the response: here are some abbreviated
logs from a long running request:

127.0.0.1 - - [22/Dec/2007:13:55:33 -0500] “GET
/admin/categories/refresh_solr/62 HTTP/1.1” 302 0
http://localhost/admin/categories/products” “Firefox/2.0.0.11” “-”
60.335 60.335
127.0.0.1 - - [22/Dec/2007:13:56:50 -0500] “GET /admin/categories
HTTP/1.1” 200 2652 “http://localhost/admin/categories/products
“Firefox/2.0.0.11” “-” 1.881 1.881

The first line is requesting the long running action (which calls fork.)
After forking, it issues a redirect (the second GET). The last two
numbers are the $request_time and $upstream_response_time.

The nginx error log includes this entry:

2007/12/22 13:55:33 [error] 3730#0: *1 upstream timed out (60: Operation
timed out) while reading upstream, client: 127.0.0.1, server:
nick.local, request: “GET /admin/categories/refresh_solr/62 HTTP/1.1”,
upstream: “http://127.0.0.1:3000/admin/categories/refresh_solr/62”,
host: “localhost”, referrer:
http://localhost/admin/categories/products

Thanks!