While it’s easy to get started developing applications using Ruby on Rails, the hard part is (as with most technologies) how to put it into production? There are a lot of options like Mongrel, nginx, Apache and JRuby, all of them difficult to evaulate without deeper knowledge of Rails and your application’s scaling needs. We will look at the available options to get a clearer picture how each setup is in different situations, and how you can utilize Capistrano for an easy deployment process in those situations. Simple as well as more complex setups will be discussed. We’ll try to include your problems as well as your experiences to discuss specific issues with deployment and scalability.
2. Who are we?
Jonathan Weiss
• Consultant for Peritor GmbH in Berlin
• Specialized in Rails, Scaling, Deployment, and Code Review
• Webistrano - Rails deployment tool
• FreeBSD Rubygems and Ruby on Rails maintainer
http://www.peritor.com
http://blog.innerewut.de
2
3. Who are we?
Mathias Meyer
• Consultant for Peritor GmbH in Berlin
• Specialized in Rails, Performance/Database Tuning,
Deployment, and Refactoring
• Maintainer of Macistrano –
Webistrano-Client for Mac OS X (and soon the iPhone),
run_later and acts_as_solr
http://www.paperplanes.de
3
9. Typical Rails Setup
• A load-balancer distributes the incoming requests
• Some load-balancers will deliver static requests themselves
• Several Rails instances handle all requests
• Number of concurrent requests equals number of Rails instances
9
14. FastCGI
• Protocol to communicate with long-running CGI applications
• Usage of either mod_fcgi with Apache 1.3 or mod_fcgi with Lighttpd
• Proxy local and remote FastCGI instances
• Oldest way of deploying Rails
• Deprecated and unstable
• Hard to debug (FastCGI protocol)
14
19. Mongrel
• Developed by Zed Shaw as an alternative to FastCGI
• Complete HTTP-Server that can load arbitrary Ruby-servlets
• Built-in Rails support
19
25. Simple Mongrel and Apache 2.2
Redirect all traffic to the Mongel cluster
25
26. A more complex example
• Redirect dynamic requests
• Serve static content
• Support cached pages
• Support maintenance page
• Enable client-side caching of
images, stylesheets, and JavaScript
• Compress output if supported
26
27. Mongrel
• Very robust
• Strict HTTP parser
• Easy to debug (HTTP!)
• Used to be defacto deployment setup with Apache 2.2 and mod_proxy_balancer
• Can be a bit difficult to setup (mongrel_cluster, ports, Apache)
• Not so easy on mass/virtual hosting
27
29. mod_rails a.k.a Phusion Passenger
• Module for Apache 2.2 (and Nginx)
• Allows Apache to control Rails instances
• Apache starts and stops application instances depending on the application load
• Able to run any Rack-compatible Ruby application (Merb, Sinatra & Co.)
• Only manages Rails on one host - no remote instances
• Combine with HTTP-Proxy / balancing solution
29
36. Phusion Passenger
• Ready for production
• Makes setup easier – on the single machine level
• Multiple servers still require load balancer
• Suitable for mass-hosting
• upcoming standard way of deploying Rails
36
38. • Ruby Runtime on the Java Virtual Machine
• Implemented in Java and Ruby
• Compiles Ruby into Java-bytecode
• Integrates with Java code and libraries
• Java’s promises of native threads and JIT
• Allows for Ruby/Rails applications to be packaged as WAR files
• WAR files deployable on any J2EE-container:
Glassfish, JBoss, Tomcat, Jetty, …
38
44. Glassfish for development
Shrunk-down version of Glassfish v3 - packaged as a gem
Can run any Rack-based application
Installation:
• $ jruby -S gem install glassfish
• $ glassfish
• There is no Step 3
44
47. Proxy Requirements
• Hide cluster backend from the user
• Load-balancer backend instances
• Recognize down hosts
• Fair scheduler
• (Deliver static content)
47
48. Apache 2.2
• Apache 2.2 introduced mod_proxy_balancer
• mod_proxy_balancer can speak to multiple backends and balance requests
• Apache can acts as a pure proxy or can also serve static files
48
49. Apache 2.2
• Apache 2.2 introduced mod_proxy_balancer
• mod_proxy_balancer can speak to multiple backends and balance requests
• Apache can acts as a pure proxy or can also serve static files
49
50. Apache 2.2
• Apache 2.2 introduced mod_proxy_balancer
• mod_proxy_balancer can speak to multiple backends and balance requests
• Apache can acts as a pure proxy or can also serve static files
50
51. Apache 2.2
Pro
• Stable, robust, and mature
• Many people know how to work with Apache
• Integrates well with other modules (SVN, DAV, Auth, …)
Con
• Apache can be complicated to configure
• The stock Apache is quite resource-hungry compared to pure proxy solutions
51
52. Nginx – From Russia with love
• Nginx - popular Russian webserver with good proxy support
• Can load-balance multiple backends and deliver static content
• Quite popular with Mongrel as the Rails backend
• Recent Passenger support
52
54. Nginx
Pro
• Stable, robust, and fast
• Uses fewer resources (CPU and RAM) than Apache for proxy-mode and static files
• Simpler configuration file
• Can directly talk to memcached - SSI
Con
• More documentation would be nice
• No equivalent for many Apache modules
54
55. Lighttpd
• Lightweight and fast webserver
• Balancing proxy support
• Good FastCGI support
• Used to be popular – until Mongrel came around
55
57. Lighttpd
Pro
• Fast and lightweight
• Uses fewer resources (CPU and RAM) than Apache for proxy-mode and static files
• Simpler configuration file
Con
• Unstable for some people
• Slow development cycle
• More documentation would be nice
• Configuration file can be too simple (virtual host aliasing)
• No equivalent for many Apache modules
• (No Passenger support)
57
58. HA-Proxy
• HAProxy – reliable, high performance TCP/HTTP load balancer
• Proxying and content inspection
• No content serving, just a proxy
• Mature proxy module (fair scheduler)
• ACL support
See also similar Pound and Pen
58
78. Ruby Enterprise Edition
• Copy-On-Write patches to Ruby 1.8
• Saves memory when spawning several Rails instances
• Used by Phusion Passenger if available
78
79. Thin, Ebb, Evented Mongrel & Co.
• Alternatives to Mongrel
• Claim to be faster, lighter, and what have you
• Rendering “Hello World” is usually not your bottleneck
Stick with stable and robust Mongrel, or better yet, with Passenger
79
92. Basic Ingredients - Variables
• Configure basic project information
• Override Capistrano’s default assumptions
• Once set, variables are available globally
• Defined using the set method
92
93. Basic Ingredients - Roles
• Define types of servers
• Default roles
• :www
• :app
• :db
• All can point to the same server
• But all three must be defined
• At least one database server needs to be primary
93
94. Basic Ingredients - Roles
Define custom roles as you please
Can be reused when defining tasks
94
95. Basic Ingredients - Tasks
• Define an atomic set of actions for Capistrano
• Can be called from the command line
• Or other tasks
95
96. Basic Ingredients - Tasks
To find all the tasks available in your project, use
96
97. Basic Ingredients - Namespaces
Group tasks together logically
Namespaces and tasks are separated with “:”
97
100. Get Your Capistrano On
config/deploy.rb, application specific configuration
100
101. Capistrano’s Defaults
• Your SCM is Subversion
• Deployment directory is /u/apps/#{application_name}
• User for SCM and SSH is the currently logged-in user
• Commands are run with sudo
101
107. The Deployment Lifecycle
The initial deployment
1. Checks the revision from the local machine
2. Checks out the code on the remote machines
3. Sets a link called current pointing to the lates release
4. Runs the migrations
5. Fires up application servers
107
109. The Deployment Lifecycle
Subsequent deployments
1. Checks the revision from the local machine
2. Checks out the code on the remote machines
3. Updates current link
4. Restarts application servers
109
129. The Rest
• Gem dependencies
• Support for deploying through gateway servers
• Parallel execution on multiple servers
• Server setup with deprec gem
129
134. Vlad the Deployer
• Simple, sometimes too simple
• No callback mechanism, instead the Rake syntax must be used
• Very non-verbose output, using --trace recommended
134
135. Chef
• System Integration Framework
• Written in Ruby – inspired by Puppet
• Manage multiple nodes
• Configuration
• Packages
• Custom scripts and commands
135
141. Chef and chef-deploy
• In heavy development: sometimes unstable and hard to debug
• Be prepared to get your hands dirty
• Better suited for configuration than deployment
• Community recipes at
http://github.com/opscode/cookbooks
141
144. Webistrano
• Web-UI to Capistrano
• Manages projects and their stages
• Alerting and Accounting
• Scriptable and extendable
• BSD License
http://labs.peritor.com/webistrano
144
145. Macistrano
• Mac-GUI to Webistrano
• Fire and monitor deployments from your desktop
http://github.com/mattmatt/macistrano
145
150. Tasks
• Make memcached restart with every deploy
• (Usually not a good idea, but why not?)
150
151. Tasks
• Make Apache recognize maintenance.html and display it if exists
151
152. Maintenance Page
• Create symbolic link to /etc/apache2/mods-available/rewrite.load in /etc/apache2/
mods-enabled
• Update virtual host configuration with rewrite rules
• Run cap deploy:web:disable
• Hook it into the deployment process
152
153. Tasks
• Deploy a Rack-based application
• Install Sinatra locally and on the server
• git://github.com/mattmatt/railswaycon.git
• Create deployment configuration
• Create Apache configuration
153
158. Monit
• Process-level monitoring
• Checks PID-files, ports, and permissions
• Reacts by executing a script and/or alerting
• Has a web GUI for administering nodes
158
164. Munin
• Host-level monitoring
• Master periodically asks nodes for local data
• Checks system resources and records historical data
• Allows to recognize trends and make predictions
• Alerting support
164
168. Exception Monitoring
• Monitor errors raised by your application
• Usually notifying you by email
• Good old exception_notification Plugin
• Exceptions as a Service
168
176. Full Text Search Engine
Separate Service
• Creates full text index
• Application queries search daemon
• Index update through application or
database
Possible Engines
• Ferret
• Sphinx
• Solr
• Lucene
• …
176
177. Search Slave
Database replication slave
• Has complete dataset
• Migrates slow search queries from master
• Can use different database table engine
177
178. Database Index
PostgreSQL Tsearch2
• Core since 8.3
• Allows to create full text index on multiple columns
or arbitrary SQL expressions
MySQL MyISAM FULLTEXT index
• Only works with MySQL <= 5.0 and MyISAM tables
• Full text index on multiple columns
178
179. What to use?
Different characteristics
• Real-time updates and stale data
• Lost updates
• Performance
• Document content and format
• Complexity
179
181. Problem
Long running tasks
• Resizing uploaded images
• Mailing
• Computing an expensive operation
• Accessing slow back-ends
When running inside request-response-cycle
• Blocks user
• Blocks Rails instance
• Hard to monitor and debug
181
187. Cloud Infrastructure
Servers come and go
• You do not know your servers before deploying
• Restarting is the same as introducing a new machine
You can’t hardcode IPs
database.yml
187
188. Solution #1
Query and manually adjust
• Servers do not change that often
• New nodes probably need manual intervention
• Use AWS ElasticIPs to ease the pain
Set servers dynamically AWS Elastic IP
188
189. Solution #2
Use a central directory service
• A central place to manage your running instances
• Instances query the directory and react
189
190. Solution #2
Use a central directory service
• A central place to manage your running instances
• Instances query the directory and react
190