SlideShare ist ein Scribd-Unternehmen logo
1 von 49
Downloaden Sie, um offline zu lesen
Rails Caching Secrets: 
From the Edge! 
Michael May | @ohaimmay | austinonrails | 10/28/2014
We’re Hiring! 
Distributed Systems! Ruby C Go Perl JS
We are here 
• Rails caching best practices 
• Dynamic content 
• Edge caching / Content Delivery Networks 
• Edge caching dynamic content with Rails
Rails caching 
• Query/SQL 
• Page/Action (removed from Rails 4 core!) 
• Asset 
• Fragment
Rails caching 
config.action_controller.perform_caching = true
Query caching 
• Automagically done by rails when 
perform_caching = true 
• Not cached between requests! 
• Could just store the query result in a variable
Custom Query Caching 
class Product < MyActiveModel 
def self.latest 
Rails.cache.fetch("latest", expires_in: 8.hours) do 
Product.last(50) 
end 
end 
end
Asset Pipeline 
• Serve static assets from nginx or apache 
• config.serve_static_assets = false 
• Enable Compression* 
• config.assets.compress = true 
• # Rails 4 
config.assets.css_compressor = :yui 
config.assets.js_compressor = :uglifier 
• Asset Digests 
• config.assets.digest = true
Enable Compression* 
Compress all responses with gzip, deflate, etc. 
# in application.rb 
module FastestAppEver 
class Application < Rails::Application 
config.middleware.use Rack::Deflater 
end 
end 
* http://robots.thoughtbot.com/content-compression-with-rack-deflater
$ curl -sv -H “Accept-Encoding: deflate”  
http://fast.mmay.rocks/catz.json 
* Connected to fast.mmay.rocks (127.0.0.1) port 666 
> GET /catz.json HTTP/1.1 
> User-Agent: curl 
> Host: fast.mmay.rocks:666 
> Accept-Encoding: deflate,gzip 
> 
< HTTP/1.1 200 OK 
< Content-Type: application/json; charset=utf-8 
< Vary: Accept-Encoding 
< Content-Encoding: deflate 
< Cache-Control: max-age=60, s-maxage=3600 
< Transfer-Encoding: chunked 
< 
* magical encoded bytes* 
V*.I,)-VRJ-*RN@ ɥEEy%9
Before 
After
Asset Caching 
• Configure an asset host if needed 
• config.action_controller.asset_host = 
ENV[‘FASTLY_CDN_URL'] 
• Cache-Control like a pro 
• config.static_cache_control = 
'public, s-maxage=15552000, maxage=2592000'
HTTP Headers 
RFC 2616 Section 14
Cache-Control HTTP Header 
“public, maxage=2592000, s-maxage=15552000” 
public 
“please cache me” 
maxage=2592000 
“keep me for 30 days” 
s-maxage=15552000 
“PROXIES ONLY! - Keep me for 180 days”
Bonus Cache-Control 
Directives! 
• stale-while-revalidate 
• Serve the cached (stale) content for n seconds while you re-fetche the new content in 
the background 
• Cache-Control: maxage=604800, stale-while-revalidate=3600 
• “Serve stale for up to an hr while you fetch the latest behind the scenes” 
• stale-if-error 
• If the re-fetch fails within n seconds of the content becoming stale, serve the cached 
content 
• Cache-Control: max-age=604800, stale-if-error=86400 
• “Serve stale for up to an hr if origin responds with 4xx or 5xx”
ETags 
• Automatically added into requests with 
Rack::ETag 
• Rails renders response every time to calculate 
etag 
• Override default with Conditional GETs 
• stale?(@model) 
• fresh_when(@model)
The Vary HTTP Header 
• Change response base on the value of another 
HTTP Header 
• Example: 
“Vary: Accept-Encoding” 
Accept-Encoding: gzip => Serve Response A 
Accept-Encoding: deflate => Serve Response B 
• “This response changes for different values of 
the Accept-Encoding header”
Vary Best Practices 
• Please do not Vary on User-Agent 
• There are THOUSANDS of these! 
• Limits caching benefits - almost Impossible to 
serve the same response more than once! 
• In general, avoid varying on anything other than 
content encoding
Dynamic Content 
• Changes are unpredictable! 
• User driven events 
• Can’t just set a Time To Live (TTL) 
• Frequently, but not continuously changing 
• Actually static for short periods of time (we 
can cache static things)!
Dynamic Content Caching 
• Usually don’t (╯°□°)╯︵ ┻━┻ 
• Edge Side Includes (ESI) 
• Dynamic Site Acceleration (DSA)
Fragment Caching 
The rails answer to caching dynamic HTML 
# products/index.html.erb 
<% cache(cache_key_for_products) do %> 
<% Product.all.each do |p| %> 
<%= link_to p.name, product_url(p) %> 
<% end %> 
<% end %> 
# products_controller.rb 
def update 
… 
expire_fragment(cache_key_for_products) 
… 
end
Nested Fragment Caching 
<% cache(cache_key_for_products) do %> 
All available products: 
<% Product.all.each do |p| %> 
<% cache(p) do %> 
<%= link_to p.name, product_url(p) %> 
<% end %> 
<% end %> 
<% end %>
Nested Fragment 
• Tedious 
• Comb through (probably terrible) view code 
• Cache keys are weird 
• “A given key should always return the same content.” - Rails 
• But I like “A given key should always return the most up-to-date 
content” - like a DB primary key 
• Hacking around cache limitations 
• Memcache and wildcard purging
Nested Fragment 
• Garbage left in the cache 
• Defaults writing to disk 
• What about dynamic API caching? 
• “The caching itself happens in the views based 
on partials rendering the objects in question” 
• Take control over your cached data!
Edge Caching 
with things like CDNs
Edge Caches 
• Geographically distributed 
• Highly optimized storage and network 
(nanoseconds count) 
• Move content physically closer to end-users 
• DECREASE LATENCY! 
(speed of light sux lol)
#cachemoney 
• Less requests/bandwidth back to your origin 
server 
• Avoid complex or less efficient strategies 
• Edge Side Includes (ESI) 
• Fragment view caching
Edge caching 
dynamic content
Our approach to dynamic 
content 
• Tag content with Surrogate-Key HTTP headers 
• Programmatically purge (~150ms globally) 
• By Surrogate-Key 
• By resource path 
• Real-time analytics and log streaming 
• Optimize the pieces of the network we control
Tagging responses 
with Surrogate-Keys
class ProductsController < ApplicationController 
# set Cache-Control, strip Set-Cookie 
before_filter :set_cache_control_headers,only [:index,:show] 
def index 
@products = Product.last(10) 
# set Surrogate-Key: products 
set_surrogate_key_header @products.table_key 
respond_with @products 
end 
def show 
@product = Products.find(params[:id]) 
# set Surrogate-Key: product/666 
set_surrogate_key_header @product.record_key 
respond_with @product 
end 
end
Purge on updates
class ProductsController < ApplicationController 
def create 
@product = Product.new(params) 
if @product.save 
# purge Surrogate-Key: products 
@product.purge_all 
render @product 
end 
end 
...
def update 
@product = Product.find(params[:id]) 
if @product.update(params) 
# purge Surrogate-Key: product/666 
@product.purge 
render @product 
end 
end
fastly-rails 
github.com/fastly/fastly-rails
Edge caching in 
practice
Watch out for Set-Cookie! 
• Nothing with a Set-Cookie header is cached (by 
default) 
• Authentication frameworks/middleware might 
inject Set-Cookie after the rails stack removes it 
• Avoid caching pains by knowing when, where, 
and how you use Set-Cookie
Edge scripting with VCL 
(varnish config lang)
VCL 
• Fastly VCL Extensions 
• date/time, geoip, hashing, strings, etc. 
• Do application logic at the CDN edge
URL Rewriting 
• Filter bad requests 
• Normalize or block paths 
• Apache, nginx 
• if ($invalid_referer) { return 403; } 
• You can do this at the edge!
Synthetic Responses
What can we do better? 
• Add better caching defaults? 
• Cache-Control, stale-while-revalidate, stale-if-error 
• Re-use existing rails cache interfaces for edge 
caching? 
• ActiveSupport::Cache::EdgeStore 
• Better integration with HTTP accelerators like 
Varnish?
Takeaways 
• Take advantage of Rails built-in caching 
• Get fancy with Cache-Control directives 
• Use Google PageSpeed Insights (chrome plugin 
adds it to dev tools) 
• Dynamic edge caching is all about the power of 
purge! 
• Similar school of thought to rails action caching
Questions? 
Michael May || @ohaimmay 
cool links: 
fastly-rails - github.com/fastly/fastly-rails 
surrogate keys - fastly.com/blog/surrogate-keys-part-1 
cache-control tutorial - docs.fastly.com/guides/tutorials/cache-control-tutorial 
serve stale cache-control - fastly.com/blog/stale-while-revalidate 
vary header best practices - fastly.com/blog/best-practices-for-using-the-vary-header 
caching like & share buttons - fastly.com/blog/caching-like-and-share-buttons 
pagespeed insights - developers.google.com/speed/pagespeed

Weitere ähnliche Inhalte

Was ist angesagt?

Nginx - Tips and Tricks.
Nginx - Tips and Tricks.Nginx - Tips and Tricks.
Nginx - Tips and Tricks.
Harish S
 
London devops logging
London devops loggingLondon devops logging
London devops logging
Tomas Doran
 

Was ist angesagt? (20)

Load Balancing with Nginx
Load Balancing with NginxLoad Balancing with Nginx
Load Balancing with Nginx
 
Integrated Cache on Netscaler
Integrated Cache on NetscalerIntegrated Cache on Netscaler
Integrated Cache on Netscaler
 
Nginx: Accelerate Rails, HTTP Tricks
Nginx: Accelerate Rails, HTTP TricksNginx: Accelerate Rails, HTTP Tricks
Nginx: Accelerate Rails, HTTP Tricks
 
HTTP caching with Varnish
HTTP caching with VarnishHTTP caching with Varnish
HTTP caching with Varnish
 
Supercharging Content Delivery with Varnish
Supercharging Content Delivery with VarnishSupercharging Content Delivery with Varnish
Supercharging Content Delivery with Varnish
 
Nginx - Tips and Tricks.
Nginx - Tips and Tricks.Nginx - Tips and Tricks.
Nginx - Tips and Tricks.
 
Usenix LISA 2012 - Choosing a Proxy
Usenix LISA 2012 - Choosing a ProxyUsenix LISA 2012 - Choosing a Proxy
Usenix LISA 2012 - Choosing a Proxy
 
Varnish 4 cool features
Varnish 4 cool featuresVarnish 4 cool features
Varnish 4 cool features
 
5 things you didn't know nginx could do
5 things you didn't know nginx could do5 things you didn't know nginx could do
5 things you didn't know nginx could do
 
Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!Extending functionality in nginx, with modules!
Extending functionality in nginx, with modules!
 
ReplacingSquidWithATS
ReplacingSquidWithATSReplacingSquidWithATS
ReplacingSquidWithATS
 
Apache Traffic Server & Lua
Apache Traffic Server & LuaApache Traffic Server & Lua
Apache Traffic Server & Lua
 
How to monitor NGINX
How to monitor NGINXHow to monitor NGINX
How to monitor NGINX
 
Building your own CDN using Amazon EC2
Building your own CDN using Amazon EC2Building your own CDN using Amazon EC2
Building your own CDN using Amazon EC2
 
Using NGINX as an Effective and Highly Available Content Cache
Using NGINX as an Effective and Highly Available Content CacheUsing NGINX as an Effective and Highly Available Content Cache
Using NGINX as an Effective and Highly Available Content Cache
 
ITB2017 - Nginx Effective High Availability Content Caching
ITB2017 - Nginx Effective High Availability Content CachingITB2017 - Nginx Effective High Availability Content Caching
ITB2017 - Nginx Effective High Availability Content Caching
 
Varnish Configuration Step by Step
Varnish Configuration Step by StepVarnish Configuration Step by Step
Varnish Configuration Step by Step
 
Web前端性能优化 2014
Web前端性能优化 2014Web前端性能优化 2014
Web前端性能优化 2014
 
London devops logging
London devops loggingLondon devops logging
London devops logging
 
How To Set Up SQL Load Balancing with HAProxy - Slides
How To Set Up SQL Load Balancing with HAProxy - SlidesHow To Set Up SQL Load Balancing with HAProxy - Slides
How To Set Up SQL Load Balancing with HAProxy - Slides
 

Ähnlich wie Rails Caching Secrets from the Edge

ASP.NET Scalability - DDD7
ASP.NET Scalability - DDD7ASP.NET Scalability - DDD7
ASP.NET Scalability - DDD7
Phil Pursglove
 
ASP.NET Scalability - VBUG London
ASP.NET Scalability - VBUG LondonASP.NET Scalability - VBUG London
ASP.NET Scalability - VBUG London
Phil Pursglove
 
ASP.NET Scalability - NxtGen Oxford
ASP.NET Scalability - NxtGen OxfordASP.NET Scalability - NxtGen Oxford
ASP.NET Scalability - NxtGen Oxford
Phil Pursglove
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache Cayenne
WO Community
 
ASP.NET Scalability - WebDD
ASP.NET Scalability - WebDDASP.NET Scalability - WebDD
ASP.NET Scalability - WebDD
Phil Pursglove
 

Ähnlich wie Rails Caching Secrets from the Edge (20)

Accelerating Rails with edge caching
Accelerating Rails with edge cachingAccelerating Rails with edge caching
Accelerating Rails with edge caching
 
Caching your rails application
Caching your rails applicationCaching your rails application
Caching your rails application
 
Mini-Training: To cache or not to cache
Mini-Training: To cache or not to cacheMini-Training: To cache or not to cache
Mini-Training: To cache or not to cache
 
Where Django Caching Bust at the Seams
Where Django Caching Bust at the SeamsWhere Django Caching Bust at the Seams
Where Django Caching Bust at the Seams
 
Azure appfabric caching intro and tips
Azure appfabric caching intro and tipsAzure appfabric caching intro and tips
Azure appfabric caching intro and tips
 
More Cache for Less Cash (DevLink 2014)
More Cache for Less Cash (DevLink 2014)More Cache for Less Cash (DevLink 2014)
More Cache for Less Cash (DevLink 2014)
 
Best practices para publicar un WebSite con SharePoint Server 2010
Best practices para publicar un WebSite con SharePoint Server 2010Best practices para publicar un WebSite con SharePoint Server 2010
Best practices para publicar un WebSite con SharePoint Server 2010
 
Day 7 - Make it Fast
Day 7 - Make it FastDay 7 - Make it Fast
Day 7 - Make it Fast
 
ASP.NET Scalability - DDD7
ASP.NET Scalability - DDD7ASP.NET Scalability - DDD7
ASP.NET Scalability - DDD7
 
cache concepts and varnish-cache
cache concepts and varnish-cachecache concepts and varnish-cache
cache concepts and varnish-cache
 
ASP.NET Scalability - VBUG London
ASP.NET Scalability - VBUG LondonASP.NET Scalability - VBUG London
ASP.NET Scalability - VBUG London
 
Nginx caching
Nginx cachingNginx caching
Nginx caching
 
JCache Using JCache
JCache Using JCacheJCache Using JCache
JCache Using JCache
 
ASP.NET Scalability - NxtGen Oxford
ASP.NET Scalability - NxtGen OxfordASP.NET Scalability - NxtGen Oxford
ASP.NET Scalability - NxtGen Oxford
 
Advanced Apache Cayenne
Advanced Apache CayenneAdvanced Apache Cayenne
Advanced Apache Cayenne
 
Rails caching
Rails cachingRails caching
Rails caching
 
AppFabric Velocity
AppFabric VelocityAppFabric Velocity
AppFabric Velocity
 
ASP.NET Scalability - WebDD
ASP.NET Scalability - WebDDASP.NET Scalability - WebDD
ASP.NET Scalability - WebDD
 
Caching in Kentico 11
Caching in Kentico 11Caching in Kentico 11
Caching in Kentico 11
 
awergaezrg
awergaezrgawergaezrg
awergaezrg
 

Kürzlich hochgeladen

Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Kürzlich hochgeladen (20)

Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 

Rails Caching Secrets from the Edge

  • 1. Rails Caching Secrets: From the Edge! Michael May | @ohaimmay | austinonrails | 10/28/2014
  • 2. We’re Hiring! Distributed Systems! Ruby C Go Perl JS
  • 3. We are here • Rails caching best practices • Dynamic content • Edge caching / Content Delivery Networks • Edge caching dynamic content with Rails
  • 4. Rails caching • Query/SQL • Page/Action (removed from Rails 4 core!) • Asset • Fragment
  • 6. Query caching • Automagically done by rails when perform_caching = true • Not cached between requests! • Could just store the query result in a variable
  • 7. Custom Query Caching class Product < MyActiveModel def self.latest Rails.cache.fetch("latest", expires_in: 8.hours) do Product.last(50) end end end
  • 8. Asset Pipeline • Serve static assets from nginx or apache • config.serve_static_assets = false • Enable Compression* • config.assets.compress = true • # Rails 4 config.assets.css_compressor = :yui config.assets.js_compressor = :uglifier • Asset Digests • config.assets.digest = true
  • 9. Enable Compression* Compress all responses with gzip, deflate, etc. # in application.rb module FastestAppEver class Application < Rails::Application config.middleware.use Rack::Deflater end end * http://robots.thoughtbot.com/content-compression-with-rack-deflater
  • 10. $ curl -sv -H “Accept-Encoding: deflate” http://fast.mmay.rocks/catz.json * Connected to fast.mmay.rocks (127.0.0.1) port 666 > GET /catz.json HTTP/1.1 > User-Agent: curl > Host: fast.mmay.rocks:666 > Accept-Encoding: deflate,gzip > < HTTP/1.1 200 OK < Content-Type: application/json; charset=utf-8 < Vary: Accept-Encoding < Content-Encoding: deflate < Cache-Control: max-age=60, s-maxage=3600 < Transfer-Encoding: chunked < * magical encoded bytes* V*.I,)-VRJ-*RN@ ɥEEy%9
  • 11.
  • 13. Asset Caching • Configure an asset host if needed • config.action_controller.asset_host = ENV[‘FASTLY_CDN_URL'] • Cache-Control like a pro • config.static_cache_control = 'public, s-maxage=15552000, maxage=2592000'
  • 14. HTTP Headers RFC 2616 Section 14
  • 15. Cache-Control HTTP Header “public, maxage=2592000, s-maxage=15552000” public “please cache me” maxage=2592000 “keep me for 30 days” s-maxage=15552000 “PROXIES ONLY! - Keep me for 180 days”
  • 16. Bonus Cache-Control Directives! • stale-while-revalidate • Serve the cached (stale) content for n seconds while you re-fetche the new content in the background • Cache-Control: maxage=604800, stale-while-revalidate=3600 • “Serve stale for up to an hr while you fetch the latest behind the scenes” • stale-if-error • If the re-fetch fails within n seconds of the content becoming stale, serve the cached content • Cache-Control: max-age=604800, stale-if-error=86400 • “Serve stale for up to an hr if origin responds with 4xx or 5xx”
  • 17. ETags • Automatically added into requests with Rack::ETag • Rails renders response every time to calculate etag • Override default with Conditional GETs • stale?(@model) • fresh_when(@model)
  • 18. The Vary HTTP Header • Change response base on the value of another HTTP Header • Example: “Vary: Accept-Encoding” Accept-Encoding: gzip => Serve Response A Accept-Encoding: deflate => Serve Response B • “This response changes for different values of the Accept-Encoding header”
  • 19. Vary Best Practices • Please do not Vary on User-Agent • There are THOUSANDS of these! • Limits caching benefits - almost Impossible to serve the same response more than once! • In general, avoid varying on anything other than content encoding
  • 20. Dynamic Content • Changes are unpredictable! • User driven events • Can’t just set a Time To Live (TTL) • Frequently, but not continuously changing • Actually static for short periods of time (we can cache static things)!
  • 21. Dynamic Content Caching • Usually don’t (╯°□°)╯︵ ┻━┻ • Edge Side Includes (ESI) • Dynamic Site Acceleration (DSA)
  • 22. Fragment Caching The rails answer to caching dynamic HTML # products/index.html.erb <% cache(cache_key_for_products) do %> <% Product.all.each do |p| %> <%= link_to p.name, product_url(p) %> <% end %> <% end %> # products_controller.rb def update … expire_fragment(cache_key_for_products) … end
  • 23. Nested Fragment Caching <% cache(cache_key_for_products) do %> All available products: <% Product.all.each do |p| %> <% cache(p) do %> <%= link_to p.name, product_url(p) %> <% end %> <% end %> <% end %>
  • 24. Nested Fragment • Tedious • Comb through (probably terrible) view code • Cache keys are weird • “A given key should always return the same content.” - Rails • But I like “A given key should always return the most up-to-date content” - like a DB primary key • Hacking around cache limitations • Memcache and wildcard purging
  • 25. Nested Fragment • Garbage left in the cache • Defaults writing to disk • What about dynamic API caching? • “The caching itself happens in the views based on partials rendering the objects in question” • Take control over your cached data!
  • 26. Edge Caching with things like CDNs
  • 27. Edge Caches • Geographically distributed • Highly optimized storage and network (nanoseconds count) • Move content physically closer to end-users • DECREASE LATENCY! (speed of light sux lol)
  • 28.
  • 29.
  • 30.
  • 31.
  • 32. #cachemoney • Less requests/bandwidth back to your origin server • Avoid complex or less efficient strategies • Edge Side Includes (ESI) • Fragment view caching
  • 34. Our approach to dynamic content • Tag content with Surrogate-Key HTTP headers • Programmatically purge (~150ms globally) • By Surrogate-Key • By resource path • Real-time analytics and log streaming • Optimize the pieces of the network we control
  • 35. Tagging responses with Surrogate-Keys
  • 36. class ProductsController < ApplicationController # set Cache-Control, strip Set-Cookie before_filter :set_cache_control_headers,only [:index,:show] def index @products = Product.last(10) # set Surrogate-Key: products set_surrogate_key_header @products.table_key respond_with @products end def show @product = Products.find(params[:id]) # set Surrogate-Key: product/666 set_surrogate_key_header @product.record_key respond_with @product end end
  • 38. class ProductsController < ApplicationController def create @product = Product.new(params) if @product.save # purge Surrogate-Key: products @product.purge_all render @product end end ...
  • 39. def update @product = Product.find(params[:id]) if @product.update(params) # purge Surrogate-Key: product/666 @product.purge render @product end end
  • 41. Edge caching in practice
  • 42. Watch out for Set-Cookie! • Nothing with a Set-Cookie header is cached (by default) • Authentication frameworks/middleware might inject Set-Cookie after the rails stack removes it • Avoid caching pains by knowing when, where, and how you use Set-Cookie
  • 43. Edge scripting with VCL (varnish config lang)
  • 44. VCL • Fastly VCL Extensions • date/time, geoip, hashing, strings, etc. • Do application logic at the CDN edge
  • 45. URL Rewriting • Filter bad requests • Normalize or block paths • Apache, nginx • if ($invalid_referer) { return 403; } • You can do this at the edge!
  • 47. What can we do better? • Add better caching defaults? • Cache-Control, stale-while-revalidate, stale-if-error • Re-use existing rails cache interfaces for edge caching? • ActiveSupport::Cache::EdgeStore • Better integration with HTTP accelerators like Varnish?
  • 48. Takeaways • Take advantage of Rails built-in caching • Get fancy with Cache-Control directives • Use Google PageSpeed Insights (chrome plugin adds it to dev tools) • Dynamic edge caching is all about the power of purge! • Similar school of thought to rails action caching
  • 49. Questions? Michael May || @ohaimmay cool links: fastly-rails - github.com/fastly/fastly-rails surrogate keys - fastly.com/blog/surrogate-keys-part-1 cache-control tutorial - docs.fastly.com/guides/tutorials/cache-control-tutorial serve stale cache-control - fastly.com/blog/stale-while-revalidate vary header best practices - fastly.com/blog/best-practices-for-using-the-vary-header caching like & share buttons - fastly.com/blog/caching-like-and-share-buttons pagespeed insights - developers.google.com/speed/pagespeed