This deck is from a live presentation on 7/31/13 which featured an in-depth look at optimizing production apps on Heroku. This is the second session in a two part series for production apps on Heroku. Video recording can be found here https://vimeo.com/71442888. Check out vimeo.com/69263217 for the first session on setting up and running production apps.
Topics for this presentation include:
* Using a CDN to increase app performance
* How to manage the asset pipeline
* Using heroku-pg-extras to gain visibility into database performance
* How to manage database migrations
* How to use a database follower for transactional and analytics database reads
* How to set up caching with Heroku add-ons
* Useful labs features
Looking for 1:1 assistance with your production apps, please contact our Customer Success team here - lp.heroku.com/ProductionApps.html?mkt_tok=3RkMMJWWfF9wsRow5%2FmYJoDpwmWGd5mht7VzDtPj1OY6hBkvKrWJK1TtuMFUGpsqOOGbEw0bBg%3D%3D
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Optimizing production apps on heroku 7.31.13
1. Join the conversation via #herokuJoin the conversation via #heroku
Optimizing Production AppsOptimizing Production Apps
on Herokuon Heroku
Ryan Huber, Customer AdvocateRyan Huber, Customer Advocate
@ryan_huber@ryan_huber
Greg Nokes, Technical Account ManagerGreg Nokes, Technical Account Manager
@tsykoduk@tsykoduk
2. Join the conversation via #herokuJoin the conversation via #heroku
IntroductionsIntroductions
Ryan Huber
Customer Advocate
@ryan_huber
Greg Nokes
Technical Account Manager
@tsykoduk
3. Join the conversation via #herokuJoin the conversation via #heroku
AgendaAgenda
Using CDN to increase app performance
Managing Asset Pipeline (RoR specific)
PG Extras - Postgres
Postgres Database Migrations
Postgres Database Followers
Database Caching
Recommended Monitoring Tools
4. Join the conversation via #herokuJoin the conversation via #heroku
AssumptionsAssumptions
Existing Heroku User
General understanding of Heroku / CLI
Have installed Toolbelt & created / pushed apps
General understanding of Postgres / SQL
Have provisioned Postgres databases on Heroku
*** This webinar is being recorded and distributed online ***
5. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
6. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
Processes assets for use by Caching
7. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
Two hard problems in Computer Science:
1. Cache Invalidation
2. Naming Things
3. Off by One errors
8. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
Helps with Cache Invalidation and Naming Things
9. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
What about uploading to S3?
10. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
NO
11. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
Then you have 2 sets of files to manage
12. Join the conversation via #herokuJoin the conversation via #heroku
Asset PipelineAsset Pipeline
Leave them on the Dyno
Use a Edgecache CDN such as:
CDN Sumo
Cloudfront
CDNetworks
Akamai
13. Join the conversation via #herokuJoin the conversation via #heroku
Why Use a CDN?Why Use a CDN?
14. Join the conversation via #herokuJoin the conversation via #heroku
CDN vs S3CDN vs S3
Application Assets User Generated Assets
15. Join the conversation via #herokuJoin the conversation via #heroku
S3 Best PracticesS3 Best Practices
Direct Upload
Pass-through Upload
* If processing is required *
https://devcenter.heroku.com/articles/s3
16. Join the conversation via #herokuJoin the conversation via #heroku
CDN Best PracticesCDN Best Practices
Cache/Pull CDN
Sync/Push CDN
* Automatic Update*
* Manual Update*
Cache/Pull CDN Recommended
CDN Sumo (Heroku
Addon)https://addons.heroku.com/cdn_sumo
17. Join the conversation via #herokuJoin the conversation via #heroku
PG ExtrasPG Extras
http://www.craigkerstiens.com/2012/10/01/understanding-postgres-performance/
http://www.craigkerstiens.com/2013/01/10/more-on-postgres-performance/
18. Join the conversation via #herokuJoin the conversation via #heroku
PG ExtrasPG Extras
A Heroku plugin for awesome pg:* commands that
are also great and fun and super.
19. Join the conversation via #herokuJoin the conversation via #heroku
PG ExtrasPG Extras
There is a lot in there
20. Join the conversation via #herokuJoin the conversation via #heroku
PG ExtrasPG Extras
We will talk about two
1. heroku pg:cache_hit
2. heroku pg:index_usage
21. Join the conversation via #herokuJoin the conversation via #heroku
heroku pg:cache_hitheroku pg:cache_hit
Shows the cache hit ratio.
A good measure of database sizing
We like to see it at 99%
22. Join the conversation via #herokuJoin the conversation via #heroku
heroku pg:index_usageheroku pg:index_usage
Shows the index hit ratio on each table
Big, heavily used tables need to have 99 – 100%
23. Join the conversation via #herokuJoin the conversation via #heroku
Postgres Database MigrationPostgres Database Migration
24. Join the conversation via #herokuJoin the conversation via #heroku
Dev / Basic vs Production DBsDev / Basic vs Production DBs
Dev / Basic
* Not suitable for production
applications
* Expected uptime of 99.5%
* Many level features not supported:
Fork, follow
* Row number limitation: 10K for
Dev, 10M for Basic.
* The database instance is shared
among many other customers
Production
* Designed for higher uptime,
99.95%
* No row level limitation
* You get your own database
instance
* Fork, follow supported
* Suitable for production applications
25. Join the conversation via #herokuJoin the conversation via #heroku
Migrating Dev / Basic DBsMigrating Dev / Basic DBs
https://devcenter.heroku.com/articles/upgrade-heroku-postgres-with-pgbackups
26. Join the conversation via #herokuJoin the conversation via #heroku
Migrating Production DBsMigrating Production DBs
https://devcenter.heroku.com/articles/heroku-postgres-follower-databases
27. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabasesFollower Databases
Starter:
Development
No Fork/Follow
99.5% uptime
28. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabasesFollower Databases
Production:
Can Fork/Follow
99.95% uptime
29. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabasesFollower Databases
30. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabasesFollower Databases
Why?
31. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabaseFollower Database
HA
32. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabaseFollower Database
Analytics / Reporting
33. Join the conversation via #herokuJoin the conversation via #heroku
Follower DatabasesFollower Databases
Octopus gem (https://github.com/tchandy/octopus)
34. Join the conversation via #herokuJoin the conversation via #heroku
Overcoming Postgres Connection LimitsOvercoming Postgres Connection Limits
35. Join the conversation via #herokuJoin the conversation via #heroku
Overcoming Postgres Connection LimitsOvercoming Postgres Connection Limits
Limit the number of connections
https://devcenter.heroku.com/articles/forked-pg-connections
36. Join the conversation via #herokuJoin the conversation via #heroku
Overcoming Postgres Connection LimitsOvercoming Postgres Connection Limits
Sometimes that’s not enough
37. Join the conversation via #herokuJoin the conversation via #heroku
Overcoming Postgres Connection LimitsOvercoming Postgres Connection Limits
https://github.com/gregburek/heroku-buildpack-pgbouncer
38. Join the conversation via #herokuJoin the conversation via #heroku
Caching for Profit & PerformanceCaching for Profit & Performance
39. Join the conversation via #herokuJoin the conversation via #heroku
Caching for Profit & PerformanceCaching for Profit & Performance
https://devcenter.heroku.com/articles/memcachier
http://guides.rubyonrails.org/caching_with_rails.html
40. Join the conversation via #herokuJoin the conversation via #heroku
Performance MonitoringPerformance Monitoring
New Relic
Dyno Queuing
Runtime Metrics (https://devcenter.heroku.com/articles/log-runtime-metrics)
Log2viz (http://log2viz.herokuapp.com/)
Logging
41. Join the conversation via #herokuJoin the conversation via #heroku
New RelicNew Relic
https://devcenter.heroku.com/articles/newrelic
Ruby
Java
Python
Node
42. Join the conversation via #herokuJoin the conversation via #heroku
New Relic: BenefitsNew Relic: Benefits
https://devcenter.heroku.com/articles/newrelic
43. Join the conversation via #herokuJoin the conversation via #heroku
New Relic: Pro vs StandardNew Relic: Pro vs Standard
https://devcenter.heroku.com/articles/newrelic
44. Join the conversation via #herokuJoin the conversation via #heroku
New Relic: CaveatsNew Relic: Caveats
https://devcenter.heroku.com/articles/newrelic
45. Join the conversation via #herokuJoin the conversation via #heroku
Dyno QueuingDyno Queuing
Processing in the router
Traveling over the network to a dyno
Queuing in the TCP socket backlog
Processing by the web server
Processing by Rack middleware
https://devcenter.heroku.com/articles/newrelic#interpreting-new-relic-request-queueing
46. Join the conversation via #herokuJoin the conversation via #heroku
Runtime MetricsRuntime Metrics
Resident Memory (memory_rss)
Disk Cache Memory (memory_cache)
Swap Memory (memory_swap)
Total Memory (memory_total)
Pages Written to Disk (memory_pgpgout)
Pages Read from Disk (memory_pgpgin)
CPU Load Avg (1 min, 5 min, 15 min avgs)
https://devcenter.heroku.com/articles/log-runtime-metrics
47. Join the conversation via #herokuJoin the conversation via #heroku
Log2vizLog2viz
http://log2viz.herokuapp.com/
48. Join the conversation via #herokuJoin the conversation via #heroku
LoggingLogging
https://devcenter.heroku.com/articles/logging
49. Join the conversation via #herokuJoin the conversation via #heroku
RecapRecap
Cache Assets
PG-Extras to Understand DB Performance
Select the Right DB Plan / Configuration
Leverage App Monitoring Tools
51. Join the conversation via #herokuJoin the conversation via #heroku
Q&AQ&A
Ryan Huber
Customer Advocate
@ryan_huber
Greg Nokes
Technical Account Manager
@tsykoduk
Notas del editor
- Serving assets from a dyno increases request time - Offloading assets to a CDN significantly improves dyno performance, user experience and will help limit long running requests which can cause H12 errors.
- A CDN should be used for all application specific assets - S3 should be used for all user generated assets; this decreases your application slug - A CDN can also be used to cache S3 assets for faster upload
- Assets should be uploaded directly to S3; this is called a Direct Upload - Assets should not be uploaded to a dyno and passed to S3; this will increase request times, decrease app performance which can lead to H12 errors - If processing of an asset is required, upload asset and process it via a worker dyno or with one of the Heroku Addons https://devcenter.heroku.com/articles/s3
- Leverage a Cache/Pull CDN vs a Sync/Push CDN - Cache/Pull CDNs pull assets from app automatically if asset is not present - Sync/Push CDNs require you to upload assets manually - CDN Sumo is a Heroku addon that streamlines the process of uploading assets to a CDN (https://addons.heroku.com/cdn_sumo)
- Serving assets from a dyno increases request time - Offloading assets to a CDN significantly improves dyno performance, user experience and will help limit long running requests which can cause H12 errors.
Dev/Basic vs Production DBs - Dev/Basic databases don't have a cache, all reads are done from swap/disk Production databases have a cache which significantly improves performance Production databases also support Followers (https://devcenter.heroku.com/articles/heroku-postgres-follower-databases) and Forks (https://devcenter.heroku.com/articles/heroku-postgres-fork)
It’s quicker to promote a follower then to restore a backup
Run reports via background jobs, consoles or another app Run read requests against a less busy read-only follower How?
Point your reads at a follower, writes at the master
Postgres has a limit of 500 connections Limit the number of connections (https://devcenter.heroku.com/articles/forked-pg-connections)
PG BouncerSets up dyno wide connection pool so database connections can be reused btw dynos / processes Does not work in all cases – you’ll need to test it to make sure that it will work for you.
Rails offers a lot of ways to cache. On heroku you can leverage the memcachier addon to easily enable caching.
Caching is a great idea Use Memcachier or Redis as a cache store Find out more at
New Relic: Performance monitoring tool for Heroku Support Ruby, Java, Python and Node
New Relic: Benefits - New Relic is really good at providing a deep dive into your app to understand what components of your app are taking the longest
Pro vs Standard Two different versions - Pro & Standard Pro provides transaction breakdowns which show which component of your app is performing slowly
New Relic: Caveats - New Relic shows averages which can be problematic on Heroku. Developers need to pay attention to the poorest performing requests, what we call the 95%. You could make a change / modification to your app that significantly improves performance, but since New Relic show averages, you may see a minor improvement in response time.
Dyno Queuing: - Dyno Queuing in New Relic represents more than just dyno queue time - Dyno Queue Time includes: * Processing in the router * Traveling over the network to a dyno * Queuing in the TCP socket backlog on the dyno * Processing by the web server (eg. Unicorn, Gunicorn, mod_wsgi) * Processing by Rack middleware configured for the app - Implementing some or all of what we've outlined today should significantly decrease dyno queue time and improve application performance - https://devcenter.heroku.com/articles/newrelic#interpreting-new-relic-request-queueing
Runtime Metrics: - Injects dyno specific resource data into your logs - Resident Memory (memory_rss): The portion of the dyno’s memory (megabytes) held in RAM. - Disk Cache Memory (memory_cache): The portion of the dyno’s memory (megabytes) used as disk cache. - Swap Memory (memory_swap): The portion of the dyno’s memory (megabytes) stored on disk. Swapping is extremely slow and should be avoided. - Total Memory (memory_total): The total memory (megabytes) being used by the dyno, equal to the sum of resident, cache, and swap memory. - Pages Written to Disk (memory_pgpgout): The cumulative total of the pages written to disk. Sudden high variations on this number can indicate short duration spikes in swap usage. The other memory related metrics are point in time snapshots and can miss short spikes. - Pages Read from Disk (memory_pgpgin): The cumulative total of the pages read from disk. As with the previous metric, watch out for sudden variations. - Load Average 1m (load_avg_1m): The load average for the dyno in the last 1 minute. This reflects the number of CPU tasks that are in the ready queue (i.e. waiting to be processed). More details about how load averages are calculated can be found below. - Load Average 5m (load_avg_5m): The load average for the dyno in the last 5 minutes. Computed in the same manner as 1m load average. - Load Average 15m (load_avg_15m): The load average for the dyno in the last 15 minutes. Computed in the same manner as 1m load average. - You want to make sure you keep CPU Load Averages below a value of 4. If you see values above 4, you are experiencing runtime contention and the CPU is your bottleneck; you'll want to decrease your number of in-dyno processes (unicorn / gunicorn workers) - https://devcenter.heroku.com/articles/log-runtime-metrics
Log2viz: - App that digests the last 60 seconds of your logs leveraging runtime metrics to show a quick view of application performance - Pay special attention to 95th %; this shows you your slowest requests - 95% is what you'll want to pay attention to when doing performance optimizations; New Relic won't show you this info Also keep an eye on Memory Usage when correctly sizing in-dyno process count (unicorn / gunicorn) http://log2viz.herokuapp.com/
Logging: - Heroku caches only the most recent logs for any given application - Leveraging a Heroku addon for archiving all your logs is a critical - Logs can be leveraged to better understand application performance and Heroku specific errors - You can write custom app specific logs via standard out; this is a great way of understanding what's going on in your application Heroku's Support team (help.heroku.com) uses these logs when diving into support tickets; when no Logging Addon is provisioned against an app it's difficult for Support to understand what happened in your application. https://devcenter.heroku.com/articles/logging