Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mind the gap - filling holes in other people's ...

Mind the gap - filling holes in other people's SaaS with MongoDB

Avatar for Lindsay Holmwood

Lindsay Holmwood

May 28, 2013
Tweet

More Decks by Lindsay Holmwood

Other Decks in Programming

Transcript

  1. IE

  2. PHP + Zend + MySQL + Redis + Memcache +

    Sphinx + Nginx + apache
  3. $ gem install blitz $ blitz help Usage: blitz <command>

    <options> help - Display this help account:about - Show information about your account api:init - Validate and login with your API key couch:fuzz - Auto generate blitz tests from CouchDB curl - Run a sprint or a rush curl:help - Show help on sprint and rushing traceroute - Run traceroute remotely traceroute:help - Show help on traceroute version - Show the version of this Ruby gem $ blitz api:init # writes credentials to ~/.blitz/credentials
  4. $ blitz curl:help Usage: blitz curl <options> <url> --user-agent -A

    <string> User-Agent to send to server --cookie -b name=<string> Cookie to send to the server (multiple) --data -d <string> Data to send in a PUT or POST request --dump-header -D <file> Print the request/response headers --referer -e <string> Referer URL --help -h Help on command line options --header -H <string> Custom header to pass to server --pattern -p <s>-<e>:<d> Ramp from s to e concurrent requests in d secs --region -r <string> california|oregon|virginia|singapore|ireland| japan --status -s <number> Assert on the HTTP response status code --timeout -T <ms> Wait time for both connect and responses --user -u <user[:pass]> User and password for authentication --request -X <string> Request method to use (GET, HEAD, PUT, etc.) --variable -v <string> Define a variable to use --verbose -V Print the request/response headers --tlsv1 -1 Use TLSv1 (SSL) --sslv2 -2 Use SSLv2 (SSL) --sslv3 -3 Use SSLv3 (SSL)
  5. $ blitz curl --region australia --pattern 1-250:20 \ --timeout 10000

    --verbose http://example.org/ user growth / time
  6. $ blitz curl --region australia --pattern 1-250:20 \ --timeout 10000

    --verbose http://example.org/ user growth / time for AWS lag
  7. $ blitz curl --region australia --pattern 1-250:20 \ --timeout 10000

    --verbose http://example.org/ rushing from australia... Time Users Response Hits Timeouts Errors Hits/s Mbps 2.5s 31 -1.000s 0 0 0 8.3s 103 1.075s 146 0 9 50.53 0.88 11.2s 140 0.406s 376 0 9 79.64 1.41 14.1s 176 0.409s 682 0 9 105.24 1.86 22.8s 0 0.417s 1552 0 9 15.57 0.27 user growth / time for AWS lag
  8. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job)
  9. # ruby load_test.rb rushing from australia... Time Users Response Hits

    Timeouts Errors Hits/s Mbps 2.5s 31 -1.000s 0 0 0 8.3s 103 1.075s 146 0 9 50.53 0.88 11.2s 140 0.406s 376 0 9 79.64 1.41 14.1s 176 0.409s 682 0 9 105.24 1.86 22.8s 0 0.417s 1552 0 9 15.57 0.27
  10. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job)
  11. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job)
  12. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job)
  13. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job) puts job.result.timeline.to_json
  14. class Blitz::Curl::Rush class Point def to_json(*args) { 'timestamp' => @timestamp,

    'duration' => @duration, 'total' => @total, 'hits' => @hits, 'errors' => @errors, 'timeouts' => @timeouts, 'volume' => @volume, 'txbytes' => @txbytes, 'rxbytes' => @rxbytes, 'steps' => @steps, }.to_json end end # ...
  15. # ... class Step def to_json(*args) { 'duration' => @duration,

    'connect' => @connect, 'errors' => @errors, 'timeouts' => @timeouts, 'asserts' => @asserts, }.to_json end end end
  16. #!/usr/bin/env ruby # load_test.rb require 'blitz' arguments = "--region australia

    --pattern 1-250:60" url = "http://example.org/" command = "#{arguments} #{url}" job = Blitz::Curl.parse(command) curl = Blitz::Command::Curl.new curl.rush(job) puts job.result.timeline.to_json
  17. {"start":1335694346,"finish":1335694367,"results":[{"timestamp": 2.502626,"duration":1.13912,"total":1,"hits":1,"errors":0,"timeouts": 0,"volume":2,"txbytes":258.0,"rxbytes":17810.0,"steps":[{"duration": 2.13912,"connect":0.260004,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":5.016102,"duration":0.640047,"total":5,"hits":5,"errors": 0,"timeouts":0,"volume":4,"txbytes":1548.0,"rxbytes":90882.0,"steps": [{"duration":1.640047,"connect":0.158944,"errors":0,"timeouts": 0,"asserts":0}]},{"timestamp":7.524594,"duration":0.639987,"total": 10,"hits":10,"errors":0,"timeouts":0,"volume":5,"txbytes": 3354.0,"rxbytes":182222.0,"steps":[{"duration":1.639987,"connect":

    0.158999,"errors":0,"timeouts":0,"asserts":0}]},{"timestamp": 10.03388,"duration":0.63961,"total":20,"hits":20,"errors":0,"timeouts": 0,"volume":7,"txbytes":5418.0,"rxbytes":364902.0,"steps":[{"duration": 1.63961,"connect":0.158847,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":12.543211,"duration":0.640421,"total":31,"hits": 31,"errors":0,"timeouts":0,"volume":9,"txbytes":9030.0,"rxbytes": 565850.0,"steps":[{"duration":1.640422,"connect":0.158767,"errors": 0,"timeouts":0,"asserts":0}]},{"timestamp":15.051705,"duration": 0.639894,"total":44,"hits":44,"errors":0,"timeouts":0,"volume": 10,"txbytes":12384.0,"rxbytes":803334.0,"steps":[{"duration": 1.639894,"connect":0.158794,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":17.560136,"duration":-1.0,"total":44,"hits":44,"errors": 0,"timeouts":0,"volume":0,"txbytes":12384.0,"rxbytes":803334.0,"steps": [{"duration":0.0,"connect":0.0,"errors":0,"timeouts":0,"asserts":0}]}]}
  18. {"start":1335694346,"finish":1335694367,"results":[{"timestamp": 2.502626,"duration":1.13912,"total":1,"hits":1,"errors":0,"timeouts": 0,"volume":2,"txbytes":258.0,"rxbytes":17810.0,"steps":[{"duration": 2.13912,"connect":0.260004,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":5.016102,"duration":0.640047,"total":5,"hits":5,"errors": 0,"timeouts":0,"volume":4,"txbytes":1548.0,"rxbytes":90882.0,"steps": [{"duration":1.640047,"connect":0.158944,"errors":0,"timeouts": 0,"asserts":0}]},{"timestamp":7.524594,"duration":0.639987,"total": 10,"hits":10,"errors":0,"timeouts":0,"volume":5,"txbytes": 3354.0,"rxbytes":182222.0,"steps":[{"duration":1.639987,"connect":

    0.158999,"errors":0,"timeouts":0,"asserts":0}]},{"timestamp": 10.03388,"duration":0.63961,"total":20,"hits":20,"errors":0,"timeouts": 0,"volume":7,"txbytes":5418.0,"rxbytes":364902.0,"steps":[{"duration": 1.63961,"connect":0.158847,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":12.543211,"duration":0.640421,"total":31,"hits": 31,"errors":0,"timeouts":0,"volume":9,"txbytes":9030.0,"rxbytes": 565850.0,"steps":[{"duration":1.640422,"connect":0.158767,"errors": 0,"timeouts":0,"asserts":0}]},{"timestamp":15.051705,"duration": 0.639894,"total":44,"hits":44,"errors":0,"timeouts":0,"volume": 10,"txbytes":12384.0,"rxbytes":803334.0,"steps":[{"duration": 1.639894,"connect":0.158794,"errors":0,"timeouts":0,"asserts":0}]}, {"timestamp":17.560136,"duration":-1.0,"total":44,"hits":44,"errors": 0,"timeouts":0,"volume":0,"txbytes":12384.0,"rxbytes":803334.0,"steps": [{"duration":0.0,"connect":0.0,"errors":0,"timeouts":0,"asserts":0}]}]} protip!
  19. { "start": 1335694346, "finish": 1335694367, "results": [ { "timestamp": 2.502626,

    "duration": 1.13912, "total": 1, "hits": 1, "errors": 0, "timeouts": 0, "volume": 2, "txbytes": 258.0, "rxbytes": 17810.0, "steps": [ { "duration": 2.13912, "connect": 0.260004, "errors": 0, "timeouts": 0, "asserts": 0 } ] } # ... ] }
  20. Capture.controllers :load_tests do post :index do parser = Yajl::Parser.new data

    = parser.parse(params[:data]) @load_test = LoadTest.create(data) @load_test.id end end
  21. Capture.controllers :load_tests do post :index do parser = Yajl::Parser.new data

    = parser.parse(params[:data]) @load_test = LoadTest.create(data) @load_test.id end end
  22. Capture.controllers :load_tests do post :index do parser = Yajl::Parser.new data

    = parser.parse(params[:data]) @load_test = LoadTest.create(data) @load_test.id end end
  23. class LoadTest include MongoMapper::Document key :start, Time key :finish, Time

    key :user, String key :email, String key :login, String key :region, String key :environment, String has_many :results timestamps! end
  24. class LoadTest include MongoMapper::Document key :start, Time key :finish, Time

    key :user, String key :email, String key :login, String key :region, String key :environment, String has_many :results timestamps! end 1-to-many relationship
  25. class Result include MongoMapper::EmbeddedDocument key :timestamp, Float key :duration, Float

    key :total, Integer key :hits, Integer key :errors, Integer key :timeouts, Integer key :volume, Integer key :txbytes, Float key :rxbytes, Float has_many :steps end
  26. class Result include MongoMapper::EmbeddedDocument key :timestamp, Float key :duration, Float

    key :total, Integer key :hits, Integer key :errors, Integer key :timeouts, Integer key :volume, Integer key :txbytes, Float key :rxbytes, Float has_many :steps end 1-to-many relationship
  27. class Step include MongoMapper::EmbeddedDocument key :duration, Float key :connect, Float

    key :errors, Integer key :timeouts, Integer key :asserts, Integer end
  28. class Step include MongoMapper::EmbeddedDocument key :duration, Float key :connect, Float

    key :errors, Integer key :timeouts, Integer key :asserts, Integer end what is this?
  29. Embedded documents are almost identical to Documents with one exception:

    they are saved inside of another document instead of in their own collection. -- MongoMapper Documentation
  30. class Order include MongoMapper::Document many :line_items timestamps! end class LineItem

    include MongoMapper::EmbeddedDocument key :name, String key :quantity, Integer end Order.create(:line_items => [ LineItem.new(:name => 'Undershirt', :quantity => 5), LineItem.new(:name => 'Underwear', :quantity => 5), LineItem.new(:name => 'Socks', :quantity => 3), ])
  31. { "_id"=>BSON::ObjectId('4d39d708bcd1b368fc000004'), "created_at"=>Fri Jan 21 18:57:12 UTC 2011, "updated_at"=>Fri Jan

    21 18:57:12 UTC 2011, "line_items"=> [ {"name"=>"Undershirt", "quantity"=>5, "_id"=>BSON::ObjectId('4d39d7fc000001')}, {"name"=>"Underwear", "quantity"=>5, "_id"=>BSON::ObjectId('4d39d78fc000002')}, {"name"=>"Socks", "quantity"=>3, "_id"=>BSON::ObjectId('4d39d708d1b8fc000003')} ] }
  32. Capture.controllers :load_tests do post :index do parser = Yajl::Parser.new data

    = parser.parse(params[:data]) @load_test = LoadTest.create(data) @load_test.id end end