Wednesday, January 19, 2011

JRuby on Rails on Amazon Elastic Beanstalk

Amazon this week announced Elastic Beanstalk, a managed Apache Tomcat service for AWS. Naturally, I had to try JRuby on it.

First, the bad:
  • AWSEB is really slow to deploy stuff. Several times it got "stuck" and I waited for more than 30 minutes for it to recover. It did not appear to be an app issue, since the app came up just fine.
  • The default instance size is t1.micro. I was able to get a Rails app to boot there, but it's a very underpowered size.
  • It appears to start up JVMs with 256MB of memory max and 64MB of permgen. For a larger app, or one with many Rails instances, that might not be enough. For a "threadsafe" Rails app, though, it's plenty.
  • The default EC2 load balancer for the new Beanstalk instance is set to ping the "/" URL. If you don't rig up a / route in your Rails app (like I forgot to do) the app will come up for a few minutes and immediately get taken out.
And the good news: it works great once you get past the hassles! Here's the process that worked for my app (assuming app is already build and ready for deploy).

Preparing the app:
  • Ensure jruby-openssl is in Gemfile. Rails seems to want it in production mode.
  • Edit config/environments/production.rb to enable threadsafe mode.
  • `warble`
Preparing Elastic Beanstalk:
  • Create a new instance, specifying the .war file Warbler created above as the app to deploy
  • There is no step two
Once the instance has been prepared, you may want to resize it to something larger than t1.micro if it's meant to be a real app...but it should boot ok.



Have fun!

5 comments:

  1. Hi

    Just a quick question for someone who is only familiar with Heroku

    When you say the small memory might not be suited to an app "with many Rails instances"... what does that mean?

    I was assuming an AWS micro server would be a single Rails app (in a similar way as a Heroku dyno)

    So.... the small memory would be ok if we only intended on running one instance per Micro server?

    It would still be half the price of Heroku?

    Am I thinking about this the right way?

    I am not sure how these instances get glued together, in a way that Heroku does for dynos automatically.

    Also, I think Heroku's Varnish layer might make it potentially far more economical still ?

    Just mu (novice) thoughts

    thanks

    ReplyDelete
  2. Anonymous: The micro instance definitely does *work* for small, single-instance apps, but in my experience even for the smallest apps they throttle CPU use too heavily for it to be useful. But that's what you get for a free instance (micro is free).

    When deploying JRuby, a single process is your entire app on that machine; JRuby can either route all requests through a single instance ("threadsafe" mode) or spin up multiple copies of your app in-memory (like a cluster-in-a-can). In the latter case, micro instances would be too tightly constrained to run an app that has more than one instance, but might be ok for a single-instance or threadsafe setup.

    As far as elastically scaling, once you're hitting the limits of a given server instance, I believe AWSEB will spin up additional instances for you.

    And of course, there's the benefit that your're running JRuby, which Heroku does not support.

    ReplyDelete
  3. Interesting! Slow deployment doesn't sound too inviting though. I also wonder how this compares to Heroku performancewise. Never used JRuby before. I might make some tests...

    ReplyDelete
  4. Hey cool, this is exactly what I was thinking about this morning. And of course my generous friend Denton Gentry pointed me to this post after a half formed tweet.

    Any big spin up, delays? One of things I wasn't too crazy about on app engine with jruby was the slow vm, warmup thingy (my rough apps are slow enough).

    Hope all is well in jruby land. Look forward to faster, broader, more compatible and seductive jruby.

    ReplyDelete
  5. Hi Charles,

    Thanks doing this write up. Sorry for this noob question...but I'm wondering how do you do rake tasks on the instance generated by the Elastic Beanstalk. Am I just totally off? I just wanted to run 'rake db:create' and 'rake db:migrate'. I ssh'd in and can't find app root directory is. Maybe things are different with jRuby? Sorry, but I'm just super confused right now.

    Thanks!

    ReplyDelete