Ruby Application servers
Ruby have many application servers which are widely used in production. For this Blog post, I would like to discuss about below 5 application servers.
- Unicorn
- Phusion Passenger
- Puma
- Thin
- Falcon
This article needs understanding of below few topics.
- Why ruby requires Application servers?
- What is Global interpreter lock? - GIL
- Also read differences between Parallelism vs Concurrency You could refer below links: Parallel computing Concurrent computing
Unicorn
This is one of available open source application server available in Ruby on rails.
Unicorn spawner does forking to handle multiple requests. If you are running your application in multi-core systems you could achieve parallelism, by configuring process count in unicorn.
As this is process based, memory consumption per server instance will be more. Let’s say if your ruby process takes around 10 MB, and if you are running with 4 process (workers). Your default memory consumption per server instance will be 10*4 MB.
But if you use >= Ruby 2.0, Forking is possible with less memory consumption due to Copy-on-write advantage of Operating system. You need to make sure your are reconnecting DB, Redis, File-system connections after forking.
Unicorn doesn’t give your multi-threaded capability for handling requests.
Passenger Phusion
There are two versions available in Passenger Phusion.
- Community Editions (Open source)
- Enterprise Editions
In Community Edition, Passenger can be configured as Multi-Process server (fork based). Above description for Unicorn will be applicable for Passenger as well.
In Enterprise Edition, Passenger can be configured as both Multi-Process and Multi-threaded server.
In Multi-threaded server, with MRI as runtime, you will not be able to achieve Parallelism due to GIL (Global interpretor lock) implemented inside MRI. Due to GIL, MRI will not allow you to execute your threads parallel even in Multi core system. But you could achieve concurrency across the request. If your application is IO bounded, configuring your application in multi-threaded instead of multi-process will improve your memory footprint of your application.
If you are using multi-threaded server with JRuby run-time, You can achieve Parallelism. Jruby, Rubinius runtime doesn’t have GIL implementation.
But you need to make your code is thread-safe if you have configured your application server as multi-threaded server. Read about Thread safety in Ruby here
Passenger also supports other application like Python, Node.js. This is one of advantage of using Passenger over Unicorn/Puma.
Puma
This is one of favorite Heroku’s favorite application server. Now it’s Rails default application server. This is open and free software.
Puma gives you both Multi-threaded and Multi-process server capability for Free. This is bigger advantages for using Puma over Passenger/Unicorn for Ruby application.
Thin
Single threaded concurrent web application server. This uses event-machine (Event driven) internally to gain concurrency. Any IO calls will not block your main thread which receives the request.
Falcon
This is Fibre-based instead of thread based. Fibres in Ruby consumes very lesser memory than Thread. It would consume very lesser memory than Other application servers.