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

Edge Caching Dynamic Apps

Edge Caching Dynamic Apps

slides from GORUCO 2014

Avatar for Michael May

Michael May

June 21, 2014
Tweet

More Decks by Michael May

Other Decks in Technology

Transcript

  1. GoRuCo | 6/21/2014 | @ehm_may Overview • Caching • Content

    Delivery Networks (CDNs) • Modern Innovations in CDNs (dynamic edge caching) • Dynamic edge caching with Ruby/Rails
  2. GoRuCo | 6/21/2014 | @ehm_may Caching Foundations • I have

    data stored somewhere (HDD, DB, Cloud) • I access that data often • Move data closer to where I am • Move data to faster storage ! • Side effect: Reduce load on original storage location
  3. GoRuCo | 6/21/2014 | @ehm_may LRU Interface • set(object) -

    O(1) - stores object, calls prune( ) (if cache is full)
  4. GoRuCo | 6/21/2014 | @ehm_may LRU Interface • set(object) -

    O(1) - stores object, calls prune( ) (if cache is full) • get(key) - O(1) - returns object, moves it to the “head” of the cache
  5. GoRuCo | 6/21/2014 | @ehm_may LRU Interface • set(object) -

    O(1) - stores object, calls prune( ) (if cache is full) • get(key) - O(1) - returns object, moves it to the “head” of the cache • prune( ) - removes object from “tail” of the cache
  6. GoRuCo | 6/21/2014 | @ehm_may LRU Implementation • HashTable to

    store data - get( ) and set( ) functions • Doubly Linked List for tracking “time since last use”
  7. GoRuCo | 6/21/2014 | @ehm_may Cache Hierarchy CPU/HARDWARE CACHE (L1-L4)

    MAIN MEMORY MEMCACHED / VARNISH CACHE CONTENT DELIVERY NETWORK SOFTWARE/APPLICATION CACHE (e.g. Rails Cache)
  8. GoRuCo | 6/21/2014 | @ehm_may Cache Hierarchy CPU/HARDWARE CACHE (L1-L4)

    MAIN MEMORY MEMCACHED / VARNISH CACHE CONTENT DELIVERY NETWORK SOFTWARE/APPLICATION CACHE (e.g. Rails Cache)
  9. GoRuCo | 6/21/2014 | @ehm_may Content Delivery Network is a

    globally distributed network of cache servers
  10. GoRuCo | 6/21/2014 | @ehm_may Edge caching static content is

    easy! The Asset Pipeline builds links with the asset_host ! Rails: # config/environments/production.rb config.action_controller.asset_host = “mycdn.coolcdn.com” ! Sinatra: (with something like sinatra_asset_pipeline) # in app.rb set :assets_host, ‘mycdn.coolcdn.com’
  11. GoRuCo | 6/21/2014 | @ehm_may Content Delivery Networks • How

    data/requests get to the edge • Controlling content with HTTP Headers • Lesser known CDN features
  12. GoRuCo | 6/21/2014 | @ehm_may PUSH CDN • You “push”

    content to the CDN • Usually happens when an asset is updated • Harder to keep assets in sync • Can strain origin server when pushing
  13. GoRuCo | 6/21/2014 | @ehm_may PULL CDN • CDN “pulls”

    content from your origin server • Seamless updates when assets change • Small latency cost on first request • Acts as a reverse proxy
  14. GoRuCo | 6/21/2014 | @ehm_may How requests get to “The

    Edge” * The edge closest to you…usually
  15. GoRuCo | 6/21/2014 | @ehm_may Request Routing • Request made

    by client • Request triggers DNS lookup
  16. GoRuCo | 6/21/2014 | @ehm_may Request Routing • Request made

    by client • Request triggers DNS lookup • DNS resolves request to a geographical region
  17. GoRuCo | 6/21/2014 | @ehm_may Request Routing • Request made

    by client • Request triggers DNS lookup • DNS resolves request to a geographical region • Request forwarded to CDN Edge nearest to that region
  18. GoRuCo | 6/21/2014 | @ehm_may Cache-Control • Specify behavior intended

    to prevent caches from interfering with the request or response • Override the default caching algorithm • Specify what can be cached • Specify how long to cache
  19. GoRuCo | 6/21/2014 | @ehm_may Cache-Control: max-age! ! Indicates how

    long to keep response fresh. Respected by all shared caches (CDN) and private caches (browser).
  20. GoRuCo | 6/21/2014 | @ehm_may Cache-Control: private! ! Indicates response

    MUST NOT be cached by shared caches. However, private caches may cache.
  21. GoRuCo | 6/21/2014 | @ehm_may Cache-Control: s-maxage! ! Indicates how

    long to keep response fresh. Respected ONLY by shared caches.
  22. GoRuCo | 6/21/2014 | @ehm_may Use Cache-Control: s-maxage to specify

    different times to cache between shared and private caches
  23. GoRuCo | 6/21/2014 | @ehm_may Surrogate-Control: max-age! ! Indicates how

    long to keep response fresh. Respected ONLY by reverse proxies.
  24. GoRuCo | 6/21/2014 | @ehm_may Sneaky Example • Surrogate-Control takes

    priority over Cache-Control • Surrogate will cache for 1 year • Browser will cache for 30 minutes • Sometimes Surrogate-Control is stripped by the Surrogate
  25. GoRuCo | 6/21/2014 | @ehm_may HTTP Keep-Alive Header • Connection:

    Keep-Alive • TCP Session is kept open for an extended period • Eliminate costly TCP Handshake • In CDN Land edge nodes may keep connections alive with origin => faster cache misses (Dynamic Site Acceleration)
  26. GoRuCo | 6/21/2014 | @ehm_may Instant Purging • PURGE request

    comes in to edge node • Edge node purges and passes to on to nearest neighbors • Recurse until everyone has purged brucespang.com/bimodal
  27. GoRuCo | 6/21/2014 | @ehm_may Instant Purging • Purges happen

    globally in < 300ms on 95th percentile • Enables dynamic content caching at the edge brucespang.com/bimodal www.fastly.com/blog/building-fast-and-reliable-purging-system
  28. GoRuCo | 6/21/2014 | @ehm_may Dynamic Caching • Explain process

    • Example using Rails Fragment caching • Map fragment caching to edge caching
  29. GoRuCo | 6/21/2014 | @ehm_may Dynamic Content • Data that

    changes frequently • Frequently does not mean continuously
  30. GoRuCo | 6/21/2014 | @ehm_may Dynamic Content • Data that

    changes frequently • Frequently does not mean continuously • Periods of time where data is not being changed
  31. GoRuCo | 6/21/2014 | @ehm_may Dynamic Caching • API requests

    • Comments • News article headlines • E-commerce inventory • Search results
  32. GoRuCo | 6/21/2014 | @ehm_may Dynamic Caching - How To

    1. Create unique cache keys 2. Bind data to cache keys
  33. GoRuCo | 6/21/2014 | @ehm_may Dynamic Caching - How To

    1. Create unique cache keys 2. Bind data to cache keys 3. Purge with cache key on data updates
  34. GoRuCo | 6/21/2014 | @ehm_may # products/index.html.erb <% Product.all.each do

    |p| %> <% cache(p.cache_key) do %> <%= link_to p.name, product_url(p) %> <% end %> <% end %> ! # in products_controller.rb expire_fragment(cache_key)
  35. GoRuCo | 6/21/2014 | @ehm_may 1. Create unique cache keys

    In CDN land, Surrogate-Keys are your cache keys
  36. GoRuCo | 6/21/2014 | @ehm_may 1. Create unique cache keys

    Surrogate-Key is a HTTP Header that tells the cache to associate key(s) with response data
  37. GoRuCo | 6/21/2014 | @ehm_may 2. Bind data to cache

    keys Use Surrogate-Key on HTTP GETs GET /product/123 ! HTTP/1.1 200 OK Content-Type: text/json Surrogate-Control: max-age=86400 Surrogate-Key: products product/123 {id: 123, name: “Kewl Keyboard”, price: “$124.99”}
  38. GoRuCo | 6/21/2014 | @ehm_may 3. Purge with cache key

    on data updates PURGE Surrogate-Key on ! HTTP POST, PUT, DELETE PUT /product/123 {price: “$1.00”} ! # In PUT request handler PURGE /product/123
  39. GoRuCo | 6/21/2014 | @ehm_may Dynamic Edge Caching on Rails

    1. Extend models with surrogate key instance methods
  40. GoRuCo | 6/21/2014 | @ehm_may class Product < ActiveRecord::Base !

    def resource_key “#{table_key}/#{id}" # e.g. “products/1234” end ! def table_key self.class.table_name # e.g. “products” end end
  41. GoRuCo | 6/21/2014 | @ehm_may Dynamic Edge Caching on Rails

    1. Extend models with surrogate key instance methods 2. Add ActionController helpers to set up headers
  42. GoRuCo | 6/21/2014 | @ehm_may class ProductsController < ApplicationController before_filter

    :set_cache_control_headers, only: [:index, :show] ! def index @products = Product.all set_surrogate_key_header @product.table_key respond_with @products end ! def show @product = Products.find(params[:id]) set_surrogate_key_header @product.record_key respond_with @product end end
  43. GoRuCo | 6/21/2014 | @ehm_may class ProductsController < ApplicationController before_filter

    :set_cache_control_headers, only: [:index, :show]! ! def index @products = Product.all set_surrogate_key_header @product.table_key respond_with @products end ! def show @product = Products.find(params[:id]) set_surrogate_key_header @product.record_key respond_with @product end end
  44. GoRuCo | 6/21/2014 | @ehm_may def set_cache_control_headers(max_age = 3600) response.headers['Cache-Control']

    = "public, no-cache" response.headers['Surrogate-Control'] = "max-age=#{max_age}" request.session_options[:skip] = true # don’t cache cookies end
  45. GoRuCo | 6/21/2014 | @ehm_may class ProductsController < ApplicationController before_filter

    :set_cache_control_headers, only: [:index, :show] ! def index @products = Product.all set_surrogate_key_header @product.table_key respond_with @products end ! def show @product = Products.find(params[:id]) set_surrogate_key_header @product.record_key respond_with @product end end
  46. GoRuCo | 6/21/2014 | @ehm_may class ProductsController < ApplicationController before_filter

    :set_cache_control_headers, only: [:index, :show] ! def index @products = Product.all set_surrogate_key_header @product.table_key! respond_with @products end ! def show @product = Products.find(params[:id]) set_surrogate_key_header @product.record_key! respond_with @product end end
  47. GoRuCo | 6/21/2014 | @ehm_may Dynamic Edge Caching on Rails

    1. Extend models with surrogate key instance methods 2. Add ActionController helpers to set up headers 3. Add purge/purge_all instance methods to models
  48. GoRuCo | 6/21/2014 | @ehm_may class ProductsController < ApplicationController !

    def create @product = Product.new(params) if @product.save @product.purge_all! render @product end end
  49. GoRuCo | 6/21/2014 | @ehm_may def update @product = Product.find(params[:id])

    if @product.update(params) @product.purge! render @product end end
  50. GoRuCo | 6/21/2014 | @ehm_may def delete @product = Product.find(params[:id])

    if @product.destroy @product.purge_all! end end end
  51. GoRuCo | 6/21/2014 | @ehm_may Dynamic Edge Caching on Rails

    1. Extend models with surrogate key instance methods 2. Add ActionController helpers to set up headers 3. Add purge/purge_all instance methods to models
  52. GoRuCo | 6/21/2014 | @ehm_may In Summary • Offload static

    assets onto a content delivery network
  53. GoRuCo | 6/21/2014 | @ehm_may In Summary • Offload static

    assets onto a content delivery network • CDN Instant purging enables dynamic edge caching
  54. GoRuCo | 6/21/2014 | @ehm_may In Summary • Offload static

    assets onto a content delivery network • CDN Instant purging enables dynamic edge caching • Use fastly-rails to integrate dynamic edge caching into Rails