Sinatra deployment and performance on Slicehost, Heroku, and Google App Engine
Monday 05/18/2009 – Category: Uncategorized – 4 Comments
During Railsconf I was anxious to see what all the hype was about Sinatra. While attending Blake's Sinatra tutorial I ported the Flickr Original web service (originally in merb) to a nice and compact one-file Sinatra app. It's really nice having everything as minimal as possible and in one file.
Now, deployment.
Slicehost
I guess Thin is the standard for deploying Sinatra apps (when did mongrel go out of style?). Deploying with Thin just involves setting up a config.yml with your working directory, paths to your pid, log, rackup file, ports, etc and then setting up nginx (or whatever web server you're using) accordingly as a proxy. Deploying from scratch on Slicehost wasn't too bad...but some legwork is still required.
Heroku
I also tried deploying on Heroku. Heroku makes it dead simple to deploy an app: after setting up an account, you just need create a Heroku app which creates a remote git repo that you can push to. git push heroku automatically updates your code and redeploys your app.
Some things to note:
- If you have custom gems, you need to add them in a .gems file
- You can use your own domains by pointing a CNAME record to Heroku
Heroku makes it extremely easy to get something up and running extremely quickly. You can have as many free projects as you want, so it can be used as a quick staging server for small projects.
Google App Engine
Deploying here was quite a bit more difficult (see previous post)...I had to modify more than a couple things to get stuff working completely on the App Engine infrastructure. Luckily jruby and the appengine sdk provide a number of scripts to pack and deploy your app. GAE gives a nice dashboard of different metrics (req/s, ms/req, etc) as well as stats on your current load, logs, bandwidth, and more.
How does performance compare? Running the same ab test gave these results:
| Platform | Requests per second | Time per request (ms) |
|---|---|---|
| Slicehost | 9.16 | 327.612 |
| Heroku | 7.71 | 389.157 |
| GAE | 4.89 | 614.014 |
Not suprisingly, my 512slice came out on top, but Heroku wasn't far behind (blossom with 1 dyno)...can't beat that for the price of free-99. Google App Engine was only able to serve half the requests per second. So until deploying on GAE gets more streamlined, I think I'll be deploying more apps to Heroku.
Sinatra on Google App Engine
Monday 05/18/2009 – Category: Uncategorized – No Comments
I attended a JRuby on Google App Engine talk during Railsconf and have been anxious to try deploying a Ruby application on the platform. This tutorial gives a good walkthrough and I was able to get a Sinatra app up and running on GAE, but not without a few hiccups and hurdles.
Some things I ran across:
- You need to have Java enabled on your GAE account. It can take up to a few days to get approved for the early look program.
- The rflickr gem I'm using in my Sinatra app relies on on xmlrpc and net:http which can't be used on GAE and was raising this error:
java.security.AccessControlException: access denied (java.lang.RuntimePermission modifyThreadGroup)
- Since GAE uses its own URL fetch library in place of net/http, you can get xmlrpc to work by doing this (thanks Ryan Brown!):
require 'appengine-apis/urlfetch' Net::HTTP = AppEngine::URLFetch::HTTP
- After I did that, the thread error went away, but I got a different error:
NoMethodError - undefined method `as_java_bytes' for #<String:0x440543>
- This time it was just a typo in the appengine-apis-0.0.4 gem. line 142 of urlfetch.rb needs to be:
request.set_payload(payload.to_java_bytes)
instead of
request.set_payload(payload.as_java_bytes)
- It takes quite a while to spin up the app for the first request...I'm not sure if there's any way around that other than setting up something to ping the app every so often
RailsConf 2009 Notes
Tuesday 05/12/2009 – Category: Uncategorized – 1 Comment
Can someone smell stale blog? It's been busy on this side and I haven't had any blogworthy material for awhile...until now.
I had the opportunity to go to RailsConf last week in Las Vegas. A lot of smart people, an overwhelming array of Apple products and geeky shirts, and tons of nerdy sessions.
Here are some brief notes from the conference:
jQuery on Rails
- good review of basic jquery selectors and more advanced DOM selectors like siblings(), nextall(), find(), filter()
- .live() can bind events after elements are added (new with jQuery 1.3)
- http://plugins.jquery.com/project/metadata/
-
<div data="{some: 'data'}"> -
$("div").metadata().some // returns 'data' - Rails 3 will implement unobtrusive js
Rack
- Rack is a generic interface for Ruby and Ruby frameworks
- provides a standard interface for creating middleware that gets run going down the stack
- sample basic Rack: http://gist.github.com/110847
- use case: progressive caching - middleware that holds a session and allows cached page to dynamically load personalized content
- use case: Twitter "embiggener" - a middleware that Twitter could use to replace all tinyurls with full urls
- http://assets.en.oreilly.com/1/event/24/And the Greatest of These Is ___ Rack Support Presentation.pdf
Sinatra
- Sinatra is a DSL (domain specific language) built on top of Rack for creating web apps in Ruby
- not an MVC architecture. routes are matched directly in the file and execute the enclosing block
- templates can be haml, erb, inline, or in-file
- gives a basic environment for app development without the whole stack
- sample: http://github.com/jzting/flickr_original_sinatra/blob/efbf3e195a242dba04c22491569e51caa12eed77/flickr_sinatra.rb
Rails 3 - some new features
- XSS protection: auto-escaped by default
- use <%=raw %> to force raw
- UJS finally!
- html5 style data-foo attributes so will validate but can also be accessed by any JS library
- cleaner router
UI fundamentals for programmers
- terseness is not a value for ui design. need explanation!
- "from the customer's point of view, the UI is the entire application"
- separate screens into REST-named conventions (new/index/show/edit)
- focus on the inside-out, content that matters first!
- "we should really have a weak tag" when applying least effective difference principle
- don't be clever by extracting html into helpers--things can change and need flexibility
- separate CSS and JS for separate actions
JS testing
- it is possible!
- http://github.com/relevance/blue-ridge/tree/master provides a set of tools for rspec-style unit testing
Chris Wanstrath (github) keynote
- focus on writing and releasing code, not on trying to become a "rock star" or "ninja"
- find a need and fulfill it, reduce friction
- https://gist.github.com/0a2655aed6a26fa15a02
Twitter on Rails
- TwitterAuth plugin makes it really easy to use the oauth in your application for SSO functionality
- speaker livecoded this: http://twisteners.heroku.com/users/jzting
JRuby on Google App Engine
- it's possible! takes quite a bit of footwork to set up though.
- limitations: no sockets, writing to filesystem, must use Google's DB system
- worth keeping an eye on in the future as a deployment option
Mountable apps in Rails 3
- will enable multiple apps that can share functionality
- a more versatile pluggable architecture (think Drupal/Wordpress-like plugins)
- example: an auth component that can be used as a SSO gatekeeper across different components (blog, admin section, etc)
Compass
- a CSS meta-framework that uses haml and sass
- can integrate popular frameworks like 960, YUI, Blueprint
- can create reusable mixins, constants
- export as expanded, compact, or compressed
- http://wiki.github.com/chriseppstein/compass
MacRuby
- a version of Ruby 1.9 that runs on top of Mac OS core frameworks
- Ruby types are ported to their Cocoa equivalent: string = NSString, array = NSArray, etc...
- so you can use Cocoa methods in addition to Ruby methods
- you can use Interface Builder like normal and use Ruby classes to power the interface
php usort
Tuesday 02/10/2009 – Category: Uncategorized – 2 Comments
I learned about a nifty PHP function that allows you to sort an array with a user-defined comparison function. This is useful if you have an array of database results and need to sort by one element in the result array (normally it would be better to sort with the SQL query but I had a mixed dataset to sort).
This is a bit similar to ranges in Ruby where the objects you're comparing have to be comparable with the <=> operator.
Sample usort with custom function:
function cmp($a, $b) { if($a["view_order"] == $b["view_order"]) return 0; else if($a["view_order"] > $b["view_order"]) return 1; else if($a["view_order"] < $b["view_order"]) return -1; } usort($tab_items, "cmp");
Google Latitude
Monday 02/9/2009 – Category: Uncategorized – No Comments
I've been wondering when Google was going to jump on the location-based service bandwagon after seeing apps like Brightkite and Loopt started getting popular when the iPhone came out.
As of now, the following devices are supported:
- Android-powered devices with Maps v3.0 and above. G1 users in the US will be receiving Maps v3.0 in a system update soon.
- Most color BlackBerry devices
- Most Windows Mobile 5.0 and above devices. Note: Some Windows Mobile devices don't support cell-ID location detection.
- Most Symbian S60 devices
No iPhone yet?? I guess I'll have to stay with the web interface (which is a bit clunky within the iGoogle framework IMO). At the very least I'd expect some automatic location detection via IP geocoding...
Recent Posts
- More Flickr Original Updates
(Sunday 01/23/2011 – Uncategorized – 13 Comments) - Flickr Original updates
(Saturday 08/7/2010 – Uncategorized – 19 Comments) - LED Light for iPhone 4
(Monday 06/28/2010 – Uncategorized – 65 Comments) - WWDC 2010: Worth Every Minute
(Monday 06/14/2010 – Uncategorized – No Comments)
