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

Facepalm To Foolproof - RailsConf 2016

Facepalm To Foolproof - RailsConf 2016

If you're new to Rails development, or just want some tips on deploying and running in production, this is the talk for you. Relying on real-world experience as part of the Heroku support team, we'll talk through common issues (and a few funny ones) we see when people take their "but it works in development!" app to a production environment.

Video: https://youtu.be/yDJV9mr--Yo

Jon McCartie

May 04, 2016
Tweet

More Decks by Jon McCartie

Other Decks in Technology

Transcript

  1. $ ab -c 100 -n 500 http://airlessbnb.com/ Requests per second:

    41.53 [#/sec] (mean) Time per request: 2407.916 [ms] (mean) Time per request: 24.079 [ms]
  2. $ ab -c 100 -n 500 http://airlessbnb.com/ Requests per second:

    41.53 [#/sec] (mean) Time per request: 2407.916 [ms] (mean) Time per request: 24.079 [ms]
  3. $ ab -c 100 -n 500 http://airlessbnb.com/ Requests per second:

    82.94 [#/sec] (mean) Time per request: 1205.721 [ms] (mean) Time per request: 12.057 [ms]
  4. ?

  5. Memory Enemies 1. Memory leaks - https:/ /github.com/schneems/derailed_benchmarks - https:/

    /blog.codeship.com/debugging-a-memory-leak-on-heroku/ 2. Too many web processes - how much memory does your app consume in one web worker? - how much memory do you have?
  6. $ free -m total used free Mem: 8014 7528 486

    -/+ buffers/cache: 2446 5567 Swap: 511 7 504 Watch Your Memory Usage
  7. $ free -m total used free Mem: 8014 7528 486

    -/+ buffers/cache: 2446 5567 Swap: 511 7 504 Watch Your Memory Usage
  8. $ free -m total used free Mem: 8014 7528 486

    -/+ buffers/cache: 2446 5567 Swap: 511 7 504 Watch Your Memory Usage
  9. $ free -m total used free Mem: 8014 7528 486

    -/+ buffers/cache: 2446 5567 Swap: 511 7 504 Watch Your Memory Usage
  10. "But Rails already logs to production.log" But we have multiple

    machines… How large is that single production.log file?
  11. Logging A twelve-factor app never concerns itself with routing or

    storage of its output stream. It should not attempt to write to or manage logfiles. Instead, each running process writes its event stream, unbuffered, to stdout. http:/ /12factor.net/
  12. $ mina deploy -----> Creating the build path -----> Cloning

    the Git repository -----> Installing gem dependencies using Bundler -----> Moving to releases/4 -----> Symlinking to current -----> Launching -----> Done. Deployed v4
  13. $ heroku create sushi Creating sushi... done $ git push

    heroku master ----> Heroku receiving push ----> Rails app detected ----> Compiled slug size is 8.0MB sushi.herokuapp.com deployed to heroku
  14. =>

  15. # Gemfile
 gem "dotenv-rails"
 # .env (.gitignore!)
 SECRET_KEY=foo # on

    heroku
 heroku config:add SECRET_KEY=foo Environment Variables
  16. # Small App (5,761 records) User Load (2.3ms) SELECT "users".*

    FROM "users" WHERE "users"."username" = "jmccartie" # Large App (231,138 records) User Load (51.7ms) SELECT "users".* FROM "users" WHERE "users"."username" = "jmccartie"
  17. # Small App (5,761 records) User Load (2.3ms) SELECT "users".*

    FROM "users" WHERE "users"."username" = "jmccartie" # Large App (231,138 records) User Load (51.7ms) SELECT "users".* FROM "users" WHERE "users"."username" = "jmccartie"
  18. # Small App (5,761 records) User Load (2.3ms) SELECT "users".*

    FROM "users" WHERE "users"."username" = "jmccartie" # Large App (231,138 records) User Load (51.7ms) SELECT "users".* FROM "users" WHERE "users"."username" = "jmccartie"
  19. # Before User Load (51.7ms) SELECT "users".* FROM "users" WHERE

    "users"."username" = "jmccartie" # After User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."username" = "jmccartie"
  20. # Before User Load (51.7ms) SELECT "users".* FROM "users" WHERE

    "users"."username" = "jmccartie" # After User Load (1.0ms) SELECT "users".* FROM "users" WHERE "users"."username" = "jmccartie"
  21. # Problem SELECT * FROM users 
 WHERE thing =

    'something' 
 AND other_thing = 'something_else' # Solution add_index :users, [:thing, :other_thing] Composite Indexes
  22. # photos_controller.rb @photos = Photo.order(:name) # index.slim - @photos do

    |photo| = image_tag photo.url p= photo.user.username
  23. Photo Load (0.2ms) SELECT "photos".* FROM "photos" ORDER BY name

    User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 5 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 4 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 7 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 8 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 9
  24. N+1

  25. # Old Photo Load (0.2ms) SELECT "photos".* FROM "photos" ORDER

    BY name User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 3 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 5 User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = 4 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 2 N+1 Queries
  26. # New Photo Load (0.2ms) SELECT "photos".* FROM "photos" LIMIT

    0, 30 User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (3, 1, 5, 4, 2) N+1 Queries
  27. # Logs 2016-04-25 20:40:17[INFO] N+1 Query: PATH_INFO: / photos; model:

    Photo => associations: [users]· Add to your finder: :include => [:users] N+1 Queries
  28. SMS