Mongrel handlers
Posted by Saulius Grigaitis
Yea, it's unusual to read blog post in English here! Because of very low feedback from Lithuanian Rails community (most of posts do not have any comment) we've decided to write in English. Probably Lithuanian Rails community is too small to give us desired feedback, so English language should help increase number of visitors and feedback. Feedback in this case means suggesting better solutions comparing to that one we write about in the post, or even deep discussion about the problem.
More I work with Rails more I understand that Rails fits 80/20 formula. Yes, I think that Rails is beautiful for 80 percents, but thanks to Rails and Ruby, we have freedom in those tricky 20%. One of those tricks is Rails applications deployment. Each Mongrel with Rails eats ~40MB RAM. This is not good if one has small amount of RAM and some actions are processed very long, say action communicates with few slow external WEB services or action is used for bigger files uploads. When such request is processing, mongrel is not available until processing is finished, so if one has only 2-3 mongrels running and action takes few seconds or more, than even low load becomes DOS attack. Mongrel handlers can help in such situations, because if the handler is pretty light, then mongrel eats only ~10 MB of RAM, so it's really good way to deliver such "time costly" operations to mongrel handlers and make available main Rails application to accept regular requests. Mongrel is multi-threaded server, but unfortunately, Ruby implements Green Threads, which is real evil when things turns to blocking system calls, so each such call hangs all threads. But ~40MB is still 4 times more than ~10MB, so instead of 2 Mongrels and Rails you can use 8 Mongrels with light handlers, also Mongrel handlers is really robust. Simple mongrel handler:
require 'rubygems'
require 'mongrel'
class HelloWorldHandler < Mongrel::HttpHandler
def process(request, response)
response.start(200) do |head, out|
puts "request got"
head["Content-Type"] = "text/html"
# here should be some real code
# ...
out << "Hello World!"
puts "request finished"
end
end
end
config = Mongrel::Configurator.new :host => ARGV[0], :port => ARGV[1] do
listener do
uri "/helloworld", :handler => HelloWorldHandler.new
end
trap("INT") { stop }
run
puts 'Started'
end
config.join
Let's start mongrel:
$ruby helloworld.rb 127.0.0.1 8000 Let's make request in the browser http://127.0.0.1:8000/helloworld
Mongrel handlers and Mongrel with Rails combination should work for most Rails projects, so try it and share your experience. Enjoy!
