0
Building Cloud Castlesand Finding Firmer FoundationsBen Scofield / @bscofieldWest End Ruby / 2 Feb 2011
this presentation is a        WORK IN PROGRESSflickr: natlockwood
THE CLOUDflickr: turtlemom_nancy
IS FAR AWAYflickr: sizemoresr
LIMITED ACCESS
DIAGNOSIS
$ ssh deploy@production.server.comLinux production.server #1 SMP Sat Dec 5 16:04:55 UTC 2009 i686To access official Ubuntu...
http://hoptoadapp.com
http://newrelic.com
http://newrelic.com - application dashboard
REPAIR
$ ssh deploy@production.server.comLinux production.server #1 SMP Sat Dec 5 16:04:55 UTC 2009 i686To access official Ubuntu...
require test_helperclass ArticleTest < ActiveSupport::TestCase  context Broken articles do    setup do      5.times.do { F...
THE CLOUDflickr: turtlemom_nancy
IS UNRELIABLEflickr: 93921318@N00
FILESYSTEMS
class Comic < ActiveRecord::Base  has_attached_file :cover, :styles => {    :thumb => "80x120>",    :medium => "300x450>" ...
class Comic < ActiveRecord::Base  has_attached_file :cover,    :storage => s3,    :s3_credentials => {       :access_key_i...
class Comic < ActiveRecord::Base  has_attached_file :cover,    :storage => s3,    :s3_credentials => {       :access_key_i...
module Watchtower  class Application < Rails::Application    # ...    require openid/store/filesystem    config.middleware...
module Watchtower  class Application < Rails::Application    # ...    require openid/store/filesystem    config.middleware...
module Watchtower  class Application < Rails::Application    # ...    require openid/store/filesystem    config.middleware...
THE CLOUDflickr: turtlemom_nancy
IS HOSTILEflickr: lensonlife
EXTERNAL SERVICES
class Searcher  def self.search(term)    Article.where([content ILIKE ?, "%#{term}%"])  endend
class Searcher  cattr_accessor :index  def self.index    @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL])    @index ...
class Searcher  cattr_accessor :index  def self.index    @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL])    @index ...
class Searcher  cattr_accessor :index  def self.index    @api ||= IndexTank::Client.new(ENV[INDEXTANK_API_URL])    @index ...
THE CLOUDflickr: turtlemom_nancy
IS RECYCLEDflickr: 3sth3r
CACHING
class BooksController < ApplicationController  caches_page :index  def index    @books = Book.all  endend
module CardCatalog  class Application < Rails::Application    # ...    ActionController::Base.cache_store = :mem_cache_sto...
module CardCatalog  class Application < Rails::Application    # ...    ActionController::Base.cache_store = :mem_cache_sto...
class BooksController < ApplicationController  def index    response.headers[Cache-Control] = public, max-age=300    @book...
class BooksController < ApplicationController  def index    response.headers[Cache-Control] = public, max-age=300    @book...
THE CLOUDflickr: turtlemom_nancy
IS MADE OF                  TINY PARTSflickr: dev07
THINKING SMALL
App
App         App               App         App      App                                 AppApp                     App     ...
$ heroku createCreating empty-sword-187....... donehttp://empty-sword-187.heroku.com/ | git@heroku.com:empty-sword-187.git...
App         App               App         App      App                                 AppApp                     App     ...
App         App               App         App      App                                 AppApp                     App     ...
HTTP and REST
PATTERNS and VIRTUES
SINGLE RESPONSIBILITYPRINCIPLE
HUMILITY
LAZINESS
PARANOIA
http://spkr8.com/t/5491Thanks!                       http://benscofield.com                                    http://herok...
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Building Cloud Castles
Upcoming SlideShare
Loading in...5
×

Building Cloud Castles

1,077

Published 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? 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.

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,077
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
4
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Building Cloud Castles"

  1. 1. Building Cloud Castlesand Finding Firmer FoundationsBen Scofield / @bscofieldWest End Ruby / 2 Feb 2011
  2. 2. this presentation is a WORK IN PROGRESSflickr: natlockwood
  3. 3. THE CLOUDflickr: turtlemom_nancy
  4. 4. IS FAR AWAYflickr: sizemoresr
  5. 5. LIMITED ACCESS
  6. 6. DIAGNOSIS
  7. 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. 8. http://hoptoadapp.com
  9. 9. http://newrelic.com
  10. 10. http://newrelic.com - application dashboard
  11. 11. REPAIR
  12. 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. 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. 14. THE CLOUDflickr: turtlemom_nancy
  15. 15. IS UNRELIABLEflickr: 93921318@N00
  16. 16. FILESYSTEMS
  17. 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. 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. 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. 20. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(/tmp) endend
  21. 21. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(./tmp) endend
  22. 22. module Watchtower class Application < Rails::Application # ... require openid/store/filesystem config.middleware.use OmniAuth::Strategies::OpenID, OpenID::Store::Filesystem.new(./tmp) endend
  23. 23. THE CLOUDflickr: turtlemom_nancy
  24. 24. IS HOSTILEflickr: lensonlife
  25. 25. EXTERNAL SERVICES
  26. 26. class Searcher def self.search(term) Article.where([content ILIKE ?, "%#{term}%"]) endend
  27. 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. 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. 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. 30. THE CLOUDflickr: turtlemom_nancy
  31. 31. IS RECYCLEDflickr: 3sth3r
  32. 32. CACHING
  33. 33. class BooksController < ApplicationController caches_page :index def index @books = Book.all endend
  34. 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. 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. 36. class BooksController < ApplicationController def index response.headers[Cache-Control] = public, max-age=300 @books = Book.all endend
  37. 37. class BooksController < ApplicationController def index response.headers[Cache-Control] = public, max-age=300 @books = Book.all endend
  38. 38. THE CLOUDflickr: turtlemom_nancy
  39. 39. IS MADE OF TINY PARTSflickr: dev07
  40. 40. THINKING SMALL
  41. 41. App
  42. 42. App App App App App AppApp App AppApp App App AppApp App App App
  43. 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. 44. App App App App App AppApp App AppApp App App AppApp App App App
  45. 45. App App App App App AppApp App AppApp App App AppApp App App App
  46. 46. HTTP and REST
  47. 47. PATTERNS and VIRTUES
  48. 48. SINGLE RESPONSIBILITYPRINCIPLE
  49. 49. HUMILITY
  50. 50. LAZINESS
  51. 51. PARANOIA
  52. 52. http://spkr8.com/t/5491Thanks! http://benscofield.com http://heroku.comBen Scofield / @bscofieldWest End Ruby / 2 Feb 2011
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×