Deploying JRuby on Google App Engine

Following the Java support announcement for Google App Engine back in April there was a small flurry of excitement about the possibility of JRuby on GAE. However, while the notion was appealing, the execution was lacking - you had to do backflips to get JRuby, servlets, and XML configs all properly bundled. Compared to the aesthetically pleasing experience of running a Sinatra, Rack, or even a Rails app with Phusion, it is no wonder that most of us promptly forgot about GAE.

Having said that, the auto-scale, load-balancing, geographic redundancy, BigTable datastore, XMPP, memcached and the newer cron and taskqueue services, are definitely all reasons to revisit the platform. John Woodell and Ryan Brown, both Google employees, have been doing terrific work on helping to lower the entry barrier. In fact, while the documentation still needs a lot of work and polish, the deployment story and the API's are basically there - it now takes just a few keystrokes to get your Ruby app on GAE!

Migrating to Google App Engine

The first thing you'll notice with App Engine is that most of your Ruby/Rails applications won't run on the platform out of the box. GAE offers a lot of great benefits, such as free load-balancing and access to the BigTable datastore amongst many other things, but it does so by abstracting or removing some of the interfaces we're all used to: there is no filesystem, BigTable is not a relational database, cron jobs are HTTP calls, and so on. While an inconvenience at first, the functionality is still there but it does require some extra work on behalf of the developer. For example, while ActiveRecord does not work at the moment, there is a DataMapper adapter that can meet all of your needs. Likewise, your code cannot make arbitrary outbound HTTP connections, but you can patch net/http to use the URLFetch API.

The net positive of all of these changes is that your application can then be uniformly scaled across the GAE infrastructure. By default, you receive a free quota for up to (roughly) five million requests, and beyond that a credit card is required. Best of all, you no longer have to think about hardware, databases, or any other supporting services. BigTable guarantees uniform access time for your queries irrespective of the size of the dataset (at a cost of higher overall latency), and CPU, memcached, and XMPP load is automatically spread within the GAE cluster. And if you're feeling adventurous, you could try deploying a distributed file system (GaeVFS), or even build your own GAE hosting environment from scratch with AppScale.

Hello World with GAE

The tooling support for getting your application on GAE is now almost fully automated. Ryan Brown's appengine-api's gem has full coverage of all the essential services, and the google-appengine gem provides a number of essential tools to help you with the generation, setup, and deployment of your applications. A simple "Hello World" Rack application is as simple as:

# install GAE tools (no JRuby required)
# > sudo gem install google-appengine

# create a rackup file: config.ru
require 'appengine-rack'

AppEngine::Rack.configure_app(
    :application => "your-app-id",
    :version => 1)

run lambda { Rack::Response.new("Hello World!") }

# start development server on local server
# > dev_appserver.rb .

# deploy application to GAE
# > appcfg.rb update .

All the configuration and deployment logic is done on your behalf by the dev_appserver and appcfg executables: packaging JRuby, creating the XML configs, authentication, etc. Deploying a Rails application, takes just a few more steps. Once the app is live, login into your GAE dashboard to scan the logs, query BigTable, or track your quotas - no need for mucking around with any system utilities!

Developing for App Engine

In theory, GAE has all the potential to become a popular deployment platform for Ruby applications (not to mention a nice market for custom Google Apps modules). The lacking resources at this point are the blog posts, developers, and the overall Ruby community mindshare around App Engine. John Woodell and Ryan Brown have done a fantastic job of lowering the entry barriers, but we're still missing the real-life production deployments that would weed out the API bugs and inconsistencies, as well as, build the overall trust in the platform.

Curious to give it a try, I took an evening to try and port a small, but non-trivial app to App Engine. Having settled on watercoolr (webhooks pubsub), I swapped out SQLite for BigTable and a few keystrokes later, I had a public watercoolr service (http://watercoolr.appspot.com) in production. No configuration, no need to worry about overloading the database. Feel free to use it for your own HTTP pubsub needs! GAE is an exciting platform, check out the examples, articles, and make sure to give it a try.


Ilya Grigorik

Ilya Grigorik is a web performance engineer and developer advocate at Google, where his focus is on making the web fast and driving adoption of performance best practices at Google and beyond.