Mongrel hangs after several hours - ruby-on-rails

I'm running into a problem in a Rails application.
After some hours, the application seems to start hanging, and I wasn't able to find where the problem was. There was nothing relevant in the log files, but when I tried to get the url from a browser nothing happened (like mongrel accept the request but wasn't able to respond).
What do you think I can test to understand where the problem is?

I might get voted down for dodging the question, but I recently moved from nginx + mongrel to mod_rails and have been really impressed. Moving to a much simpler setup will undoubtedly save me headaches in the future.
It was a really easy transition, I'd highly recommend it.

Are you sure the problem is caused by Mongrel? Have you tried running your application under WEBrick?

There are a few things you can check, but since you say there's nothing in the logs to indicate error, it sounds like you might be running into a bug when using the log rotation feature of the Logger class. It causes mongrel to lock up. Instead of relying on Logger to rotate your logs, consider using logrotate or some other external log rotation service.

Does this happen at a set number of hours/days every time? How much RAM do you have?

I had this same problem. The couple options I had narrowed it down to were MySQL adapter related. I was running on Red Hat Enterprise Linux 4 (or 5) and the app would hang after a given amount of idle time.
One suggested solution was to compile native MySQL bindings, I had been using the pure Ruby one.
The other was to set the timeout on the MySQL adapter higher than what the connection would idle out on. (I don't have the specific configuration recorded, but as I recall it was in environment.rb and it was some class variable in the mysql adapter.)
I don't recall if either of those solutions fixed it, we moved to Ubuntu shortly after that and hadn't had a problem since.

Check the Mongrel FAQ:
http://mongrel.rubyforge.org/wiki/FAQ
From my experience, mongrel hangs when:
the log file got too big (hundreds of megabytes in size). you have to setup log rotation.
the MySQL driver times out
you have to change the timeout settings of your MySQL driver by adding this to your environment.rb:
ActiveRecord::Base.verification_timeout = 14400
(this is further explained in the deployment section of the FAQ)

Unfortunately, Rails (and thereby Mongrel) using up too much memory over time and crashing is a known problem (50K+ Google entries for "Ruby, rails, crashing, memory"). The current ruby interpreter has the property that it sometimes simply fails entirely to give memory back to the system - it may reuse the memory it has but it won't give it up.
There are numerous schemes for monitoring, killing and restarting Mongrel instances in a production environment - for example: (choosing at random) rails monitor . Until the problem is fixed more decisively, one of these may be your best bet.

We have experienced this same issue. First off, install the mongrel_proctitle gem
http://github.com/rtomayko/mongrel_proctitle/tree/master
This gem/plugin will allow you to view the mongrel processes via "ps" and you can see if a Mongrel is hung. An issue we have seen with Mongrel is that it will happily accept connections and enqueue them, then wedge itself. This plugin will help you see when a Mongrel has been wedged but then you must use another monitoring app to actually restart a a wedged Mongrel, something like Monit or God
You might also want to consider putting a more balanced reverse proxy in front of your Mongrels, something HAproxy, instead of nginx, Apache or Lighttpd. With a setting of "maxconn 1" in HAproxy you can assure that the queue is being maintained by HAproxy versus Mongrel. The other reverse proxies (nginx, Apache, Lighttpd) only do round-robin which means that they can load up your Mongrel queue, inadvertently.
My personal choice is God as it is much more flexible.
tl;dr Install this gem plugin and keep an eye on your Mongrels. Try Apache+Phusion Passenger.

Related

How do you ensure your Rails server running

What is common approach to make sure that Rails server is auto-restarted after a serious crash, or a process kill? How do you deal with hanging processes? I have nginx and thin running on my production server - would you suggest to put something in between them? Or using another server?
Firstly:
You should identify the cause of a process hang or kill. These are not normal behaviours and indicate a fault somewhere.
Look for:
Insufficient memory or high load before a crash - indicates a configuration problem.
Versions of nginx that are too new.
If you're virtualising, this can cause a number of subtle problems with linux kernels that may cause segfaults. If you're using EC2, use Amazon Linux for your best chance. Ubuntu server is too bleeding edge for this purpose.
In order to do the restarts, I suggest you use monit as this is quick, easy and reliable - it's the normal way to do this.
Lastly, I suggest you set up external monitoring as well using something like Pingdom, as even monit won't catch every type fault, such as hardware failures.
If you only want to monitor an application, I'm always using Nagios with Centreon. You can set email alarming when your rails server is down. You have to setup your NRPE on every machine you want to monitor.
When an error is detected you can run a bash file to kill hanging processes and restart the server automatically. Personally, I never use that because a crash mean something goes wrong. So I do it manually in order to check everything.
Try to look here : http://www.centreon.com/

ROR very slow in development while production works fine

I have one rubyonrails app that turned really slow in development mode. Everything is fine in production, but even a simple "hello world" takes seconds in dev. I checked the session store and every possible reason i found on the net, but I didn't find the problem. Am I missing something that is common knowledge? "Completed in 1657ms (View: 226, DB: 39)"
Development is definitely slower, because it reloads all components. Production mode only loads the components when the server is started.
If you find your app is still too slow in Production mode then you can start hunting down bottlenecks. You can start by optimizing DB queries, with :include and indicies. You can also try removing your gems and plugins systematically to find the parts that are slowing down your code.
This is usually the case if you are running webrick, its so slow it makes eyes bleed.
Try installing mongrel in dev
gem install mongrel
Create a new app, see if that's slow too - that'll point to your server stack (apache, mongrel, passenger, etc.) rather than your application. If it's just your application then google rails profiling - and pick one of the many options for profiling an application.
WEBrick is doing a reverse DNS lookup on connecting IPs by default. In other words, it's trying to see if your IP address is associated with a domain name. This is unnecessary and takes too long, so you can disable it.
Open the file "l/ruby/lib/ruby/1.9.1/webrick/config.rb" and locate the line with ":DoNotReverseLookup => nil".
Change nil to true.
Enjoy!

Recommendations for a snappy Ubuntu + Rails server

I run an Ubuntu 8.04 shared host (VMWare) with Apache + Passenger (= Mod Rails), MySQL and Acts_As_Ferret (in server mode). It's too slow at the first requests. I do a lot of REST operations on it and have very few users.
Now I want to do a fresh installation...
Which setup (based on Ubuntu) do you recommend for a really snappy RoR server? (e.g. Ngnix, Thin, Mongrels or other fancy stuff)
Passenger is slow at first requests because it is idling and it shuts down all the rails processes so the first request has to load a rails process. You need to either ping regularly to avoid it idling and closing rails processes or set the idle timeout to a high value.
Look in the documentation for RailsPoolIdleTime
Check the ec2onrails mailing list, where there has been a lot of discussion of the various thin/nginx/passenger/apache alternatives and permutations, plus some hard data posted based on some decent tests.
You'll also find a nice packaged RoR/Ubuntu stack in the shape of the ec2onrails image (google ec2onrails) - it's for running on the amazon EC2 cloud but it's got a lot of nice stuff in there + capistrano tasks. Currently it's based on apache, but the version in progress is looking at the alternatives. No reason you couldn't use the same build script for a non EC2 server.
If your problem is simply the initial requests, try warming your server up before considering it live (e.g. by running a script to automatically exercise the basic operations).
Oh and I should add - are you sure the problem is your stack? More likely it is your code. It may be worth seeing where your bottlenecks are first and what you can get out of caching, improved queries and indexing, and especially memcached before tweaking anything else.
Well you could get a big speed boost by switching to Ubuntu 9.04 or even 8.10
I personally use nginx+passenger on my ubuntu stack. and use sphinx instead of ferret as well

is mod_rails or Phusion Passenger finally the answer to Ruby on Rails Deployment?

I read from some books that Phusion Passenger is the answer to easy Ruby on Rails deployment. But my friend said that first there was Apache + bunch of Mongrels, and then lighttpd, and then nginx, and now Passenger, and it seems endless...
he also said he uses dreamhost which uses Passenger, and sometimes he sees his request not being processed.
So I wonder if Passenger is the final answer to RoR deployment? do you use it and used the "ab" command to test if the site is doing quite well?
short answer: yes.
long answer: yeeeeeeeeeeeeeeesssssssssssssssss.
In all seriousness, Phusion Passenger and Ruby Enterprise Edition have taken out pretty much all of the pain of moving a Rails app into production. Previous approaches, including running a suite of Mongrels, required lots of setup surrounding starting, stopping, and recycling listener processes that Passenger handles transparently, or via simple Apache (or nginx) configuration options. And REE's complementary garbage collector means that forking off a new listener uses MUCH less memory, and is faster to boot (in Passenger's "smart" spawning mode).
Edit: #srboisvert makes a very good point; Passenger isn't the final answer to RoR deployment, but for now it's my favorite by far. One day, after a lot of hard engineering problems are solved, mainstream Ruby will probably move from hosting RoR using a multi-process model to a single-process model, which would make management even easier than with Passenger.
It's the best solution so far. I started deploying with FCGI and it was a pain. Then came mongrel and it was better. Then came mod_rails and it was WAY better.
Also a lot of large cool application are migrating to mod_rails including some by 37signals, so you know that's good.
I'll just end with a quote from DHH:
The one-piece solution with Phusion
Passenger
Once you've completed the incredibly
simple installation, you get an Apache
that acts as both web server, load
balancer, application server and
process watcher. You simply drop in
your application and touch
tmp/restart.txt when you want to
bounce it and bam, you're up and
running.
But somehow the message of Passenger
has been a little slow to sink in.
There's already a ton of big sites
running off it. Including Shopify,
MTV, Geni, Yammer, and we'll be moving
over first Ta-da List shortly, then
hopefully the rest of the 37signals
suite quickly thereafter.
So while there are still reasons to
run your own custom multi-tier setup
of manually configured pieces, just
like there are people shying away from
mod_php for their particulars, I think
we've finally settled on a default
answer. Something that doesn't require
you to really think about the first
deployment of your Rails application.
Something that just works out of the
box. Even if that box is a shared
host!
In conclusion, Rails is no longer hard
to deploy. Phusion Passenger has made
it ridiculously easy.
(via)
Yes, it is the easiest, fastest and most efficient solution.
After a lot of problems with gems like soap4r etc. had been resolved in recent releases, Passenger is the answer to deployment questions now.
We're running Apache/mod_rails in a balanced environment with HAProxy in front of 2 servers. It's much more reliable than our previous setup using Mongrel/Aapache.
It's very easy to take control over
the amount of Passenger processes running in Apache
the amount of Passenger processes running per application
and all that without the pain of tweaking a number of config files like mod_proxy, Apache.
setting up a virtual host and adding 3 lines to your Apache config is basically enough to get it running
Matt
Final Answer? Nothing is ever the final answer.
I'd say Passenger is the current answer though.
Yes. I've been running Nginx/Passenger in front of Apache for whatever still needs PHP since they released 2.2.0 a few weeks back. Especially with Ruby Enterprise Edition, it approaches what I would call "perfect".
I guess that now people will stick to mod_rails for many years. The module is really good. Configuration is dead simple. It will be hard to replace it with some better solution. Similar to mod_php. The only key component which is missing: Windows port.
In some situations (enterprise, etc) the JVM can also be a good option.

How can I find out why my app is slow?

I have a simple Rails app deployed on a 500 MB Slicehost VPN. I'm the only one who uses the app. When I run it on my laptop, it's fast enough. But the deployed version is insanely slow. It take 6 to 10 seconds to load the login screen.
I would like to find out why it's so slow. Is it my code? (Don't think so because it's much faster locally, but maybe.) Is it Slicehost's server being overloaded? Is it the Internet?
Can someone suggest a technique or set of steps I can take to help narrow down the cause of this problem?
Update:
Sorry forgot to mention. I'm running it under CentOS 5 using Phusion Passenger (AKA mod_rails or mod_rack).
If it is just slow on the first time you load it is probably because of passenger killing the process due to inactivity. I don't remember all the details but I do recall reading people who used cron jobs to keep at least one process alive to avoid this lag that can occur with passenger needed to reload the environment.
Edit: more details here
Specifically - pool idle time defaults to 2 minutes which means after two minutes of idling passenger would have to reload the environment to serve the next request.
First, find out if there's a particularly slow response from the server. Use Firefox and the Firebug plugin to see how long each component (including JavaScript and graphics) takes to download. Assuming the main page itself is what is taking all the time, you can start profiling the application. You'll need to find a good profiler, and as I don't actually work in Ruby on Rails, I can't suggest any: google "profile ruby on rails" for some options.
As YenTheFirst points out, the server software and config you're using may contribute to a slowdown, but A) slicehost doesn't choose that, you do, as Slicehost just provides very raw server "slices" that you can treat as dedicated machines. B) you're unlikely to see a script that runs instantly suddenly take 6 seconds just because it's running as CGI. Something else must be going on. Check how much RAM you're using: have you gone into swap? Is the login slow only the first time it's hit indicating some startup issue, or is it always that slow? Is static content served slow? That'd tend to mean some network issue (either on the Slicehost side, or your local network) is slowing things down, assuming you're not in swap.
When you say "fast enough" you're being vague: does the laptop version take 1 second to the Slicehost 6? That wouldn't be entirely surprising, if the laptop is decent: after all, the reason slices are cheap is because they're a fraction of a full server. You're using probably 1/32 of an 8 core machine at Slicehost, as opposed to both cores of a modern laptop. The Slicehost cores are quick, but your laptop could be a screamer compared to 1/4 of core. :)
Try to pint point where the slowness lies
1/ application is slow, or infrastructure (network + web server)
put a static file on your web server, and access it through your browser
2/ If it is fast, it is probable a problem with application + server configuration.
database access is slow
try a page with a simpel loop: is it slow?
3/ If it slow, it is probably your infrastructure. You can check:
bad network connection: do a packet capture (with Wireshark for example) and look for retransmissions, duplicate packets, etc.
DNS resolution is slow?
server is misconfigured?
etc.
What is Slicehost using to serve it?
Fast options are things like: Mongrel, or apache's mod_rails (also called passenger phusion or
something like that)
These are dedicated servers (or plugins to servers) which run an instance of your rails app.
If your host isn't using that, then it's probably defaulting to CGI. Rails comes with a simple CGI script that will serve the page, but it reloads the app for every page.
(edit: I suspect that this is the most likely case, that your app is running off of the CGI in /webapp_directory/public/dispatch.cgi, which would explain the slowness. This tends to be a default deployment on many hosts, since it doesn't require extra configuration on their part, but it doesn't give good performance)
If your host supports "Fast CGI", rails supports that too. Fast CGI will open a CGI session, and keep it open for multiple pages, so you get much better performance, but it's not nearly as good as Mongrel or mod_rails.
Secondly, is it in 'production' or 'development' mode? The easy way to tell is to go to a page in your app that gives an error. If it shows you a stack trace, it's in development mode, which is slower than production mode. Mongrel and mod_rails have startup options to determine whether to run the app in production or development mode.
Finally, if your database is slow for whatever reason, that will be a big bottleneck as well. If you do have a good deployment (Mongrel/mod_rails/etc.) in production mode, try looking into that.
Do you have a lot of data in your DB? I would double check that you have indexed all the appropriate columns- because this can make a huge difference. On your local dev system, you probably have a lot more memory than on your 500 mb slice, which would result in the DB running a lot slower if you have big, un indexed tables. You can also run the slow queries logger in MySql to pinpoint columns without indexes.
Other than that, yes- passenger will need to spool up a process for you if you have not been using the site recently. If this is the case, you should see a significant speed increase on second, and especially third and later page loads.
You might want to run a local virtual machine with 500 MB. Are you doing a lot of client-server interaction? Delays over the WAN are significant
You might want to check out RPM (there's a free "lite" version too) and/or New Relic's Tune Up.
Your CPU time is guaranteed by Slicehost using the Xen virtualization system, so it's not that. Don't have the other answers for you, sorry! Might try 'top' on a console while you're trying to access the page.
If you are using FireFox and doing localhost testing (or maybe even on LAN) you may want to try editing the network.dns.disableIPv6 setting.
Type about:config in the address bar and filter for network.dns.disableIPv6 and double-click to set to true.
This bug has been reported mainly from Vista OS's, but some others as well.
You could try running 'top' when you SSH in to see which process is heavy. If you also have problems logging you, perhaps you may try getting Statistics in the Slicehost manager.
If you discover it is MySQL's fault, consider decreasing the number of servers it can spawn.
512 seems decent for Rails application, you might have to check if you misconfigured too.

Resources