Engine Yard - www.engineyard.com App Server Arena App Server Arena Comparison of Ruby Comparison of Ruby Application Servers Application Servers J. Austin Hughey Field Application Engineer Engine Yard @jaustinhughey @openhackatx @engineyard
Nov 28, 2014
Engine Yard - www.engineyard.com
App Server ArenaApp Server ArenaComparison of Ruby Comparison of Ruby Application ServersApplication Servers
J. Austin HugheyField Application EngineerEngine Yard
@jaustinhughey
@openhackatx
@engineyard
SHAMELESS PROMOTIONAL PLUG
August 8-9, San Franciscodistill.engineyard.com
25 SpeakersWicked awesome party called “Moonshine”- Application Architecture- UX- Testing- Security
3Engine Yard - www.engineyard.com
• Lots of app servers out there, which one do you want to use and in what cases?
• Examine four app servers and look at:–Mode of Operation
–Use cases
–Configuration
–Performance
OverviewOverview
4Engine Yard - www.engineyard.com
Let’s meet the gladiatorsLet’s meet the gladiators
• Passenger– widespread use, familiar to most developers, super easy
configuration
• Unicorn– in-memory forking, fast client/request execution
• Thin– EventMachine based application server
• Puma– concurrent request processing
– Engine Yard sponsored project
5Engine Yard - www.engineyard.com
THE ARENATHE ARENA
• Basic Sinatra app with 5 request resources:– /server - display server information (very fast)
– /pi - compute Pi to 5,000 decimal places
• Mildly computationally expensive simulation
– /sleep - sleep 1, render a response (wait simulation)
• Trying to simulate I/O blocking without actually doing I/O, as well as try to create some request queuing
– /borat - uses Twitter API to get last 10 tweets from @devops_borat
• Twitter API really limited my tests here
• Trying to simulate real world network latency
– /random - one of the above (except /borat) at random
• Attempt to simulate multiple users of an application doing different things simultaneously
6Engine Yard - www.engineyard.com
THE ARENA (cont.)THE ARENA (cont.)
• High CPU Medium on Amazon EC2– Engine Yard Gentoo stable-v4 stack; 3.4 kernel
– nginx, monit, Ruby 2.0.0
– 2 virtual CPU cores
– 1.7GB Memory
PassengerVersion 3 - Version 4 not yet available on Engine Yard Cloud*
* We’re working on that.
8Engine Yard - www.engineyard.com
Passenger: Fighting Style Passenger: Fighting Style (Operation)(Operation)
• Embeds itself into nginx or Apache– nginx is used in this example as Engine Yard doesn’t make use of
Apache
• Excels in running multiple applications on the same hardware by “elastic” management of worker processes by traffic needs– Can cause problems with “always on” applications that aren’t fully
configured
• Per-worker or global request queues• Can manually route requests to specific workers based on
their load, telling each worker which requests to work• Lots of configuration options
9Engine Yard - www.engineyard.com
Passenger: Strategy (Use Cases)Passenger: Strategy (Use Cases)
• Good all around, fairly solid• Best at multiple apps on same hardware
– Only if apps are low to moderate traffic
• Many “advanced” features exist in open source alternatives for free, but are available in Passenger Enterprise– Multi-threaded requests (v4, Enterprise license)
• Puma
– Rolling restarts / zero-downtime deploys (Enterprise)
• Thin, Unicorn, Puma
• Capable of “resisting” deployment errors by refusing to sacrifice old processes for buggy new ones after a bad deploy
– Live IRB console - attach to Passenger worker pid with a REPL
• Unique to Passenger (strace is a kernel-level alternative)
10
Engine Yard - www.engineyard.com
Passenger: Training Passenger: Training (Configuration)(Configuration)
• All configuration in nginx config files– /etc/nginx/nginx.conf, servers/appname.conf, etc.
• Compiled as a module with Apache, *directly* with nginx– Must get nginx source from Phusion with their changes, compile from
there since nginx has no “plugin” architecture
• Can configure for multiple applications or just one, all within nginx configuration
• Can pre-start application workers by spoofing a request to the application domain
• Recommended worker count: varies by application/environment - possibly (num_cores * 1.5).round, but may be a problem if running multiple apps
Unicorn
12
Engine Yard - www.engineyard.com
Unicorn: Fighting Style (Operation)Unicorn: Fighting Style (Operation)
• Spins up a master process, forks into N workers– master runs “before_fork” block
– each worker runs “after_fork”
• Master monitors workers for stability– kills anything that doesn’t respond in N seconds (configurable,
default: 30)
– simply forks itself again to replace failed worker
• All workers pull from a single socket on the local machine– nginx can put all requests into that socket, workers dip the socket for
requests
• No singular thread/process to route requests to workers– All done through the socket
13
Engine Yard - www.engineyard.com
Unicorn: Strategy (Use Cases)Unicorn: Strategy (Use Cases)
• One app on hardware• Kills workers running long requests - bad choice for
websockets/long-polling (Thin would be better here)• Zero downtime deploy by QUIT+SIGUSR2 signal
– Reload master, which then kills old workers and forks itself again
• Less “WTF” than Passenger– Hopefully Passenger 4 makes that comparison totally unnecessary
14
Engine Yard - www.engineyard.com
Unicorn: Training (Configuration)Unicorn: Training (Configuration)
• unicorn.rb– before_fork, after_fork, number of workers is configurable
• Binds to a Unix socket where nginx dumps requests• timeout: sets how long to wait on a request before killing the
worker• Recommended worker count: (num_cores * 1.5).round
– Add more if you have the CPU to handle it and it won’t push you close to swap
(I really wish there was a high-res logo for this.)
16
Engine Yard - www.engineyard.com
Thin: Fighting Style (Operation)Thin: Fighting Style (Operation)
• Similar to Unicorn• One socket per worker
– configure nginx to “round robin” the requests among N workers
• EventMachine based; can work well with long-running requests
• Can perform rolling worker restarts with “onebyone” option
17
Engine Yard - www.engineyard.com
Thin: Strategy (Use Cases)Thin: Strategy (Use Cases)
• Single application on hardware• Well suited to long-running requests, live streaming,
websockets, etc. due to evented architecture
18
Engine Yard - www.engineyard.com
Thin: Training (Configuration)Thin: Training (Configuration)
• One socket/port per worker• Have nginx “load balance” requests among said workers
with an upstream definition in configuration.• Can utilize a YAML configuration file:
– environment: “production”
– servers: 5 (number of workers in cluster mode)
– onebyone: true (rolling worker restarts)
– tag: appname-thin (specific string shows up in ps output)
• Recommended worker count: (num_cores * 1.5).round– Add more if you find that you have a lot of unused CPU and you can
do so without pushing your memory close to swap
A MODERN, CONCURRENT WEB SERVER FOR RUBY
20
Engine Yard - www.engineyard.com
Puma: Fighting Style (Operation)Puma: Fighting Style (Operation)
• Threaded request processing– Even on MRI, though still bound by GVL
– Can probably get better performance on JRuby/Rubinius
• Bind to ports or socket• One socket for all workers if using sockets• Runs a request in a new thread
21
Engine Yard - www.engineyard.com
Puma: Strategy (Use Cases)Puma: Strategy (Use Cases)
• Anything that can benefit from truly concurrent execution is fair game to try Puma
• Computationally expensive tasks, not so much; tests show Puma falls over on computationally expensive operations
• Massive memory savings if running JRuby/Rubinius - one process handles everything that 5+ can
• Can do rolling restarts
22
Engine Yard - www.engineyard.com
Puma: Training (Configuration)Puma: Training (Configuration)
• One socket for all requests (easier nginx configuration)• Master process spawns workers• Can handle rolling restarts via USR1
– Master spins up new workers, only switches to them if they start correctly - somewhat like Passenger Enterprise’s deploy failure resistance
• Specify the min:max number of threads when starting Puma– bundle exec puma -t X:Y
LET THE GAMES BEGIN
27
Engine Yard - www.engineyard.com
/sleep/sleep
28
Engine Yard - www.engineyard.com
/random/random