As popular as Ruby and Rails are, it seems like this problem would already be solved. JRuby and mod_rails are all fine and dandy, but why isn't there an Apache mod for just straight Ruby?
There is Phusion Passenger, a robust Apache module that can run Rack applications with minimum configuration. It's becoming appealing to shared hosts, and turning any program into a Rack application is ridiculously easy:
A Rack application is an Ruby object
(not a class) that responds to call.
It takes exactly one argument, the
environment and returns an Array of
exactly three values: The status, the
headers, and the body.
The basic problem is this: for a long time, MRI was the only feasible Ruby Implementation. MRI has a number of problems that make it hard to embed it into another application (which is basically what mod_ruby does: it embeds MRI in Apache), especially a multi-threaded one (which Apache is). It is not particularly thread-safe and it has quite a bit of global state.
This global state means for example that if one Rails application modifies some class, then all other Rails applications that run on the same Apache server, will also see this modified class.
Another problem is that the MRI source code is not easily hackable. MRI is now more than 15 years old, and it's starting to show.
As a result of these problems, mod_ruby has never really properly worked, and at some point the maintainers simply gave up.
The C based PHP interpreter, on the other hand, was designed from day one to be run as mod_php inside Apache. Indeed, for the first couple of versions, there wasn't even a commandline version of the interpreter, mod_php was the only way to run PHP.
Phusion Passenger (aka mod_rack aka mod_rails) solves this problem by basically giving up and sidestepping the problem: they simply run a seperate copy of MRI in a seperate process for every application. It works great, and not only for Ruby. It supports WSGI (standard interface for Python Web Frameworks), Rack (standard interface for Ruby Web Frameworks) and direct support for Ruby on Rails.
My hopes are on mod_rubinius, which unfortunately doesn't exist yet. Rubinius was designed from the beginning to be thread-safe, embeddable, free of global state, not use the C stack and so on. It was designed to be able to run multiple Rubinius VMs inside one Rubinius process. This makes mod_rubinius infinitely easier to implement and maintain than mod_ruby. Unfortunately, of course, Rubinius is not released yet, and the real work on mod_rubinius cannot even begin until Rubinius is released. The good news is that mod_rubinius already has more manpower behind it than mod_ruby ever had, because it has paid developers working on it by a Rails hosting company that desperately wants to use it themselves.
It's perhaps worth double-clarifying mislav's point that mod_rails isn't actually limited to Rails code at all. The new name, mod_rack, is way better. Trivially small apps can be rackable -- their example being:
class HelloWorld
def call(env)
[200, {"Content-Type" => "text/plain"}, ["Hello world!"]]
end
end
There is one: mod_ruby, but it hasn't been maintained in about 2 years.
There is mod_rails and it can run Rack applications, what more can you need?
Related
If we say Node.js is single threaded and therefore there is just one thread that handles all the requests, what is Rails?
As I understand, Node.js is both the application and the server, but I am lost on what Rails would be? How does Rails handle requests in terms of threads/processes?
Rails can be single-threaded, it can be multi-threaded, it can be multi-process (where each process is single-threaded), or it can be multi-process where each process is multi-threaded.
It really all depends upon the app server you're using, and it kind of depends upon which Ruby implementation you're using. MRI Ruby supports native threads as of 1.9, but it still maintains what's known as a global interpreter lock. The GIL prevents the Ruby interpreter from running in multiple threads at a time. In most cases that's not really a big deal though, because the thing threads are helping with the most is waiting for I/O. If you're using either JRuby or Rubinius, they can actually run Ruby code in multiple threads at a time.
Check out the different app servers and what they offer in terms of concurrency features. Unicorn is a common one for deploying multi-process/single-threaded applications. Puma is a newer app server that's capable of running multi-threaded applications, and I believe they're either adding (or maybe have added by now, I'm not sure) the ability to run multi-process as well. Passenger seems to be able to work in every model I've listed above.
I hope this helps a little. It should at least give you some things to Google for to find more information.
I am new to Ruby on Rails and beginning a project soon. Having read about different Ruby implementations, I am wondering which setup to use. My project is expected to have a fair amount of traffic.
I am considering two optiosn: MRI Ruby (v 2.0) and JRuby (v 1.9). I am concerned that MRI Ruby is not multithreaded and am worried about the impact this will have on the web app. Perhaps the application server can eliminate this problem? Right now it looks like we will be using Puma as the application server.
In short, should I use JRuby because it is multithreaded on 1.9 or should I use MRI Ruby on 2.0?
TL;DR
Using either Puma or Passenger negates this issue because they handle threads on their own. I would recommend working with the newest version of Ruby and Rails possible as this will minimize the upgrade work you need to do when upgrading your app.
Here is a wonderful article which addresses your issue.
To summarize.
Puma is multithreaded-only. The open source variant of Phusion
Passenger is multi-process single-threaded. The Enterprise variant can
be configured to be either single-threaded or multithreaded.
...
Both Puma and Phusion Passenger Enterprise can be hybrid multi-process
multi-threaded. That is, running multiple multithreaded processes.
Hybrid mode allows Ruby and Python, which despite having a Global
Interpreter Lock, to fully utilize all CPU cores.[1] In Puma, the
hybrid mode is called "clustered".
[1] Only the case on MRI, not on JRuby and Rubinius. JRuby and Rubinius fully support multi-core threads in a single process.
In other words, both Puma and Passenger are able to treat any Ruby implementation as multi threaded. They do this by using a hybrid between multiple processes and multiple threads. This is only minimally heavier than simple multi-threading.
To be honest, I don't think this is an issue you need to worry about at this time. Wait to see how your server handles the site's traffic.
Honestly, if you are new to Ruby and Rails, just stick with the defaults - MRI in this case. Ruby enjoy several great implementations (MRI, JRuby, Rubinius, ...) that will run your web application without any problem. Starts with MRI, you can always decide to change later if needed.
You will be in a much better position to judge what is the best Ruby implementation and server when the work on your application will have started - more proficient on the plateform, and more aware of your specific challenges (not every application is that dependent on multi threading performance).
Enjoy the road!
I have done a few projects using Ruby on Rails. I am going to use JRuby on Rails and hosting it on GAE. In that case what are the stuff that I need to know while developing JRuby apps. I read that
JRuby has the same syntax
I can access Java libraries
JRuby does not have access to some gems/plugins
JRuby app would take some time to load for the first time, so I have to keep it alive by sending
request every 5 mins or so
I cannot use ActiveRecord and instead I must DataMapper
Please correct if I am wrong about any of the statements I have made and Is there anything else that I must know?. Do I need to start reading about JRuby from the scratch or I can go about as usual developing Ruby apps?
I use JRuby everyday.
True:
JRuby has the same syntax
JRuby does not have access to some gems/plugins
I can access Java libraries
Some gems/plugins have jruby-specific versions, some don't work at all. In general, I have found few problems and as the libraries and platforms have matured a lot of the problems have gone away (JRuby has become a lot better).
You can access Java, but in general why would you want to?
False:
JRuby app would take some time to load for the first time, so I have to keep it alive by sending request every 5 mins or so
I cannot use ActiveRecord and instead I must DataMapper
Although I guess it is possible to imagine a server setup where the initial startup/warmup cost of the JVM means you need to ping the server, there is nothing inherent in JRuby that makes this true. If you need to keep the server alive, you should look at your deployment environment. Something similar happens in shared-hosting with passenger where an app can go out of memory after a period of inactivity.
Also, we use ActiveRecord with no problems at all.
afaik, rails 3 is 100% compatible with jruby, so there should be no problem on that path.
like every new platform, you should make yourself comfortable with it by playing around with jruby. i recommend using RVM to do that.
as far as you questions go:
JRuby is just an other runtime like MRI or Rubinus
since JRuby is within the JVM using Java is very easy, but you can also use RJB from MRI
some gems are not compatible, when they use native c libraries, that do not run on JRuby
the JVM and your application container need startup time and some time to load your app, but that is all, there is no need for keep alive, that is wrong
you can use whatever you want, most gems are updated to be compatible with JRuby
#TobyHede mostly covered issues that you thought of you might have so I'll leave it at that.
As for other things to have in mind, it's simply a different interpreter and funny discrepancies will crop up that will take some adaptation.
some methods are implemented differently, such as sleep 10.seconds will throw exception (you have to sleep 10.seconds.to_i) and I remember getting NoMethodError on Symbol class when switching from MRI to JRuby (don't remember which method wasn't implemented), just have in mind slight variations will be there
you will experience hangs and exceptions in gems that otherwise worked for you (pry for example when listing more then one page)
some gems may work differently, pry (again) will exit if you press ctrl+c for example, pretty annoying
slightly slower load times of everything and no zeus
you'll get occasional java exception stack traces with no indication on which line of ruby code it happened
Timeout.timeout often will not work as expected when its wrapped around net code and stars align badly (this has mostly been fixed in jruby core, but it seems to still be an issue with gems that do their own netcode in pure java)
hidden problems with thread-safety in third party code How do you choose gems for a high throughput multithreaded Rails app? - stay away from EventMachine for example
threads will be awesome (due to nativeness and no gil) and fibers will suck (due to no coroutine support in JVM they're ordinary threads), this is why you often won't get a performance boost with celluloid when compared to MRI
you used to run your rails with MRI Ruby as processes in an OS, you knew how to track their PIDs, bloat, run times, kill them, monitor them etc, this part is not evident when you switch to JRuby because everything has turned to threads in a single process. Java world has very good tools to handle these issues, but its something you'll have to learn
killall -9 ruby doesn't do the trick with jruby when your console hangs (which it does more often then before), you have to ps -ef and then track the proper processes without killing your netbeans etc (minor, but annoying)
due to my last point, knowing Java and the JVM will help you get out of tight spots in certain situations (depending on what you intend to do this may be something you actually really need), choice of deployment server will increase or decrease this need (torquebox for example is a bit notorious for this, other deployment options might be simpler, see http://thenerdings.blogspot.com/2012/09/pulling-plug-on-torquebox-and-jruby-for.html)
...
Also, see what jruby team says about differences, https://github.com/jruby/jruby/wiki/DifferencesBetweenMriAndJruby
But yeah, otherwise its "just the same as MRI Ruby" :)
Lately I seem to have noticed a trend amongst some RoR developers, that is using RubyEE/Passenger/Apache type setups during their development process.
Besides the obvious "use what your clients use" idea, do these technologies enhance the development environment in any way compared to what the vanilla mongrel stack gives you ?
Ruby Enterprise Edition uses less memory than vanilla Ruby because of its improved garbage collector. May be that's something you also want to take advantage of in development.
As Passenger is running all the time you don't have to mess about stopping and starting Mongrel. Simply open your application's URL. If you're using Mac OS X there's even a handy preference pane which makes configuring Passenger to serve a Rails application a mere drag and drop away. It also lets you easily test your app in production mode.
Yes, especially using the same database. It allows you to flush out errors such as rand() vs random() and also lets you use sql specific to that database (e.g. ilike/functions/triggers/views, etc).
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.