Building Cloud Castles

  • 970 views
Uploaded on

A year ago, I was a committed VPS and dedicated-machine deployer. I thought the cloud imposed silly restrictions - how dare you take away my shell account! Whaddya mean I can't save files locally? …

A year ago, I was a committed VPS and dedicated-machine deployer. I thought the cloud imposed silly restrictions - how dare you take away my shell account! Whaddya mean I can't save files locally? Since then, I've had some interesting experiences. I've worked on big cloud-deployed systems, and certain large traditionally-deployed systems, and I've seen how a lot of the decisions that you're ... encouraged to make when designing an app to run in the cloud. Most interestingly, I've discovered how those same decisions can make for a much better app regardless of where it'll end up. In this talk, I'll share those architectural patterns with you, and show why they work. Hopefully, I'll convince all of you to build cloud castles -- even if you've got your foundation firmly on the ground.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
970
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
3
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Building Cloud Castlesand Finding Firmer FoundationsBen Scofield / @bscofieldWest End Ruby / 2 Feb 2011
  • 2. this presentation is a WORK IN PROGRESSflickr: natlockwood
  • 3. THE CLOUDflickr: turtlemom_nancy
  • 4. IS FAR AWAYflickr: sizemoresr
  • 5. LIMITED ACCESS
  • 6. DIAGNOSIS
  • 7. $ ssh deploy@production.server.comLinux production.server #1 SMP Sat Dec 5 16:04:55 UTC 2009 i686To access official Ubuntu documentation, please visit:http://help.ubuntu.com/Last login: Fri Jan 28 16:33:49 2011 from local.hostdeploy@production:~$ cd /var/log/apache2deploy@production:/var/log/apache2$ tail error.log[Sun Jan 23 06:25:02 2011] [notice] Apache/2.2.12 (Ubuntu) Phusion_Passenger/2.2.11...[Tue Jan 25 15:21:42 2011] [error] [client 118.129.166.97] Invalid URI in request G...[Fri Jan 28 12:01:50 2011] [error] [client 85.132.70.133] client sent HTTP/1.1 requ...[Sun Jan 30 06:25:06 2011] [notice] SIGUSR1 received. Doing graceful restart
  • 8. http://hoptoadapp.com
  • 9. http://newrelic.com
  • 10. http://newrelic.com - application dashboard
  • 11. REPAIR
  • 12. $ ssh deploy@production.server.comLinux production.server #1 SMP Sat Dec 5 16:04:55 UTC 2009 i686To access official Ubuntu documentation, please visit:http://help.ubuntu.com/Last login: Fri Jan 28 16:33:49 2011 from local.hostdeploy@production:~$ cd /var/www/app/current/deploy@production:/var/www/app/current$ rails console productionLoading production environment (Rails 3.0.3)>> Article.count => 112>> Article.where(:problem => true).update_attributes(:problem => false)
  • 13. require test_helperclass ArticleTest < ActiveSupport::TestCase context Broken articles do setup do 5.times.do { Factory :broken_article } end should be fixable do assert_equal 5, Article.where(:problem => true).count Article.fix_problem_articles assert_equal 0, Article.where(:problem => true).count end endendclass Article def self.fix_problem_articles where(:problem => true).update_attributes(:problem => false) endend
  • 14. THE CLOUDflickr: turtlemom_nancy
  • 15. IS UNRELIABLEflickr: 93921318@N00
  • 16. FILESYSTEMS
  • 17. class Comic < ActiveRecord::Base has_attached_file :cover, :styles => { :thumb => "80x120>", :medium => "300x450>" }end$ cd public/system$ ls /covers10/ 12/ 53/ 81/$ ls /covers/10/medium/ original/ thumb/$ ls /covers/10/mediumbatman-450.png
  • 18. class Comic < ActiveRecord::Base has_attached_file :cover, :storage => s3, :s3_credentials => { :access_key_id => ENV[s3_key], :secret_access_key => ENV[s3_secret] }, :bucket => comicsapp, :url => ":s3_path_url", :s3_headers => { Expires => 1.year.from_now.httpdate }, :styles => { :thumb => "80x120>", :medium => "300x450>" }end
  • 19. class Comic < ActiveRecord::Base has_attached_file :cover, :storage => s3, :s3_credentials => { :access_key_id => ENV[s3_key], :secret_access_key => ENV[s3_secret] }, :bucket => comicsapp, :url => ":s3_path_url", :s3_headers => { Expires => 1.year.from_now.httpdate }, :styles => { :thumb => "80x120>", :medium => "300x450>" }end
  • 20. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(/tmp) endend
  • 21. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(./tmp) endend
  • 22. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(./tmp) endend
  • 23. THE CLOUDflickr: turtlemom_nancy
  • 24. IS HOSTILEflickr: lensonlife
  • 25. EXTERNAL SERVICES
  • 26. class Searcher def self.search(term) Article.where([content ILIKE ?, "%#{term}%"]) endend
  • 27. class Searcher cattr_accessor :index def self.index @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL]) @index = @api.indexes articles end def self.search(term) raw = self.index.search(term, :function => 1) results = raw[results].to_a article_ids = results.map {|result| result[docid] } unsorted = Article.published.where(:id => article_ids) results.map { |result| unsorted.find {|u| u.id.to_i == result[docid].to_i} }.compact endend
  • 28. class Searcher cattr_accessor :index def self.index @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL]) @index = @api.indexes articles end def self.search(term) results = begin raw = self.index.search(term, :function => 1) raw[results].to_a rescue URI::InvalidURIError # An IndexTank error occurred search_by_sql(term)[results] end article_ids = results.map {|result| result[docid] } unsorted = Article.published.where(:id => article_ids) results.map { |result| unsorted.find {|u| u.id.to_i == result[docid].to_i} }.compact end def self.search_by_sql(term) {results => Article.where([content ILIKE ?, "%#{term}%"]). map {|a| {docid => a.id}}} endend
  • 29. class Searcher cattr_accessor :index def self.index @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL]) @index = @api.indexes articles end def self.search(term) results = begin raw = self.index.search(term, :function => 1) raw[results].to_a rescue URI::InvalidURIError # An IndexTank error occurred search_by_sql(term)[results] end article_ids = results.map {|result| result[docid] } unsorted = Article.published.where(:id => article_ids) results.map { |result| unsorted.find {|u| u.id.to_i == result[docid].to_i} }.compact end def self.search_by_sql(term) {results => Article.where([content ILIKE ?, "%#{term}%"]). map {|a| {docid => a.id}}} endend
  • 30. THE CLOUDflickr: turtlemom_nancy
  • 31. IS RECYCLEDflickr: 3sth3r
  • 32. CACHING
  • 33. class BooksController < ApplicationController caches_page :index def index @books = Book.all endend
  • 34. module CardCatalog class Application < Rails::Application # ... ActionController::Base.cache_store = :mem_cache_store, "memcache_host" endendclass BooksController < ApplicationController caches_action :index def index @books = Book.all endend
  • 35. module CardCatalog class Application < Rails::Application # ... ActionController::Base.cache_store = :mem_cache_store, "memcache_host" endendclass BooksController < ApplicationController caches_action :index def index @books = Book.all endend
  • 36. class BooksController < ApplicationController def index response.headers[Cache-Control] = public, max-age=300 @books = Book.all endend
  • 37. class BooksController < ApplicationController def index response.headers[Cache-Control] = public, max-age=300 @books = Book.all endend
  • 38. THE CLOUDflickr: turtlemom_nancy
  • 39. IS MADE OF TINY PARTSflickr: dev07
  • 40. THINKING SMALL
  • 41. App
  • 42. App App App App App AppApp App AppApp App App AppApp App App App
  • 43. $ heroku createCreating empty-sword-187....... donehttp://empty-sword-187.heroku.com/ | git@heroku.com:empty-sword-187.gitGit remote heroku added$ git push heroku masterCounting objects: 5, done.Delta compression using up to 4 threads.Compressing objects: 100% (3/3), done.Writing objects: 100% (3/3), 285 bytes, done.Total 3 (delta 2), reused 0 (delta 0)-----> Heroku receiving push-----> Rails app detected-----> Detected use of caches_page Installing caches_page_via_http plugin... done-----> Detected Rails is not set to serve static_assets Installing rails3_serve_static_assets... done-----> Gemfile detected, running Bundler version 1.0.7 Unresolved dependencies detected; Installing... Using --without development:test Fetching source index for http://rubygems.org/ ...
  • 44. App App App App App AppApp App AppApp App App AppApp App App App
  • 45. App App App App App AppApp App AppApp App App AppApp App App App
  • 46. HTTP and REST
  • 47. PATTERNS and VIRTUES
  • 48. SINGLE RESPONSIBILITYPRINCIPLE
  • 49. HUMILITY
  • 50. LAZINESS
  • 51. PARANOIA
  • 52. http://spkr8.com/t/5491Thanks! http://benscofield.com http://heroku.comBen Scofield / @bscofieldWest End Ruby / 2 Feb 2011