Varnish beyond basic web acceleration - DAHO.AM 2019

Varnish beyond basic web acceleration - DAHO.AM 2019

Slides for my "advanced Varnish" talk at the DAHO.AM 2019 developer conference in Munich (Germany).

More information about this presentation can be found on https://feryn.eu/speaking/varnish-beyond-basic-web-acceleration-dahoam2019/

Ca901ddcea38854b9783781c91fc87c9?s=128

Thijs Feryn

May 28, 2019
Tweet

Transcript

  1. None
  2. Slow websites SUCK

  3. WEB PERFORMANCE IS AN ESSENTIAL PART OF THE USER EXPERIENCE

  4. SLOW ~ DOWN

  5. None
  6. None
  7. None
  8. THROWING SERVERS AT THE PROBLEM

  9. MO' MONEY MO' SERVERS MO' PROBLEMS

  10. IDENTIFY SLOWEST PARTS

  11. OPTIMIZE

  12. AFTER A WHILE YOU HIT THE LIMITS

  13. CACHE

  14. HI, I'M THIJS

  15. I'M AN EVANGELIST AT

  16. None
  17. None
  18. +-5,000,000 WEBSITES 20% OF THE TOP 10K WEBSITES

  19. None
  20. I'M @THIJSFERYN

  21. None
  22. BEYOND BASIC WEB ACCELERATION?

  23. BASIC

  24. CONTENT DELIVERY CHALLENGES

  25. HEAVY COMPUTING

  26. NETWORK CAPACITY

  27. SERVER CAPACITY

  28. IMPACT ON YOUR SERVERS

  29. DON’T RECOMPUTE IF THE DATA HASN’T CHANGED

  30. REVERSE CACHING PROXY

  31. NORMALLY USER SERVER

  32. WITH REVERSE CACHING PROXY USER PROXY SERVER

  33. None
  34. WHY NOT USE A CDN?

  35. VARNISH IS CDN SOFTWARE!

  36. VARNISH CAN BE THERE TO PROTECT YOUR SERVERS FROM YOUR

    CDN
  37. CDNS WITH MANY POINTS OF PRESENCE WILL DDOS YOUR ORIGIN

  38. WHY IS VARNISH SO POWERFUL?

  39. WHY IS VARNISH SO POWERFUL? ✓ EXTREMELY LOW RESOURCE ✓

    EXTREMELY STABLE ✓ 100 GBIT PER SERVER ✓ NO DISK ACCESS AT RUNTIME ✓ REQUEST COALESCING ✓ VARNISH CONFIGURATION LANGUAGE ✓ VMODS ✓ COMPLIES TO HTTP BEST PRACTICES ✓ ENTERPRISE FEATURES*
  40. ORIGIN VARNISH REQUEST COALESCING

  41. POWER THE REASON WHY PEOPLE TRUST VARNISH

  42. HTTP THE REASON WHY PEOPLE USE VARNISH

  43. VCL THE REASON WHY PEOPLE ❤ VARNISH

  44. HTTP

  45. HTTP CACHING MECHANISMS Expires: Sat, 09 Sep 2017 14:30:00 GMT

    Cache-control: public, max-age=3600, s-maxage=86400 Cache-control: private, no-cache, no-store
  46. CACHE VARIATIONS Vary: Accept-Language

  47. CONDITIONAL REQUESTS HTTP/1.1 200 OK Host: localhost Etag: 7c9d70604c6061da9bb9377d3f00eb27 Content-type:

    text/html; charset=UTF-8 Hello world output GET / HTTP/1.1 Host: localhost
  48. CONDITIONAL REQUESTS HTTP/1.1 304 Not Modified Host: localhost Etag: 7c9d70604c6061da9bb9377d3f00eb27

    GET / HTTP/1.1 Host: localhost If-None-Match: 7c9d70604c6061da9bb9377d3f00eb27
  49. IN AN IDEAL WORLD

  50. ✓STATELESS ✓WELL-DEFINED TTL ✓CACHE / NO-CACHE PER RESOURCE ✓CACHE VARIATIONS

    ✓CONDITIONAL REQUESTS ✓PLACEHOLDERS FOR NON-CACHEABLE CONTENT IN AN IDEAL WORLD
  51. REALITY SUCKS

  52. None
  53. None
  54. TIME TO LIVE

  55. CACHE VARIATIONS

  56. LEGACY

  57. VARNISH CONFIGURATION LANGUAGE

  58. DOMAIN-SPECIFIC LANGUAGE, COMPILED TO C

  59. HOOKS INTO FINITE STATE MACHINE

  60. INFLUENCE CACHING BEHAVIOR

  61. INFLUENCE CACHING BEHAVIOR ✓ WHAT TO CACHE ✓ WHAT NOT

    TO CACHE ✓ HOW LONG TO CACHE ✓ HOW TO CACHE ✓ HOW TO EMPTY THE CACHE ✓ CHANGE REQUEST/RESPONSE/PAYLOAD
  62. THE VARNISH FLOW

  63. None
  64. None
  65. sub vcl_recv { if (req.url ~ "^/status\.php$" || req.url ~

    "^/update\.php$" || req.url ~ "^/admin$" || req.url ~ "^/admin/.*$" || req.url ~ "^/flag/.*$" || req.url ~ "^.*/ajax/.*$" || req.url ~ "^.*/ahah/.*$") { return (pass); } } URL blacklist example
  66. sub vcl_recv { if (req.url ~ "^/some-page" return (hash); }

    } URL whitelist example
  67. vcl 4.0; sub vcl_recv { if (req.http.Cookie) { set req.http.Cookie

    = ";" + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(SESS[a-z0-9]+|SSESS[a-z0-9]+|NO_CACHE)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.Cookie == "") { unset req.http.Cookie; } else { return (pass); } } } Cookie example
  68. sub vcl_recv { if (req.http.Cookie) { set req.http.Cookie = ";"

    + req.http.Cookie; set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";"); set req.http.Cookie = regsuball(req.http.Cookie, ";(language)=", "; \1="); set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", ""); set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", ""); if (req.http.cookie ~ "^\s*$") { unset req.http.cookie; return(pass); } return(hash); } } sub vcl_hash { hash_data(regsub( req.http.Cookie, "^.*language=([^;]*);*.*$", "\1" )); } Cookie cache variation
  69. THE VMOD ECOSYSTEM HTTPS://VARNISH-CACHE.ORG/VMODS/ HTTPS://DOCS.VARNISH-SOFTWARE.COM/VARNISH-CACHE-PLUS/VMODS/

  70. NEXT LEVEL

  71. NOT JUST A CACHE NOT JUST "TAKE IT OR LEAVE

    IT"
  72. AN HTTP LOGIC BOX

  73. DECISION MAKING IN THE EDGE

  74. CONTENT TRANSFORMATION IN THE EDGE

  75. CACHING THE UNCACHEABLE

  76. VARNISH DOESN'T JUST ACCELERATE WEB PAGES

  77. WEB/API CDN STREAMING

  78. ONLINE VIDEO STREAMING

  79. OVERTTHETOP

  80. None
  81. PACKAGING

  82. HTTP VIDEO PACKAGING FORMATS ✓ HLS ✓ MPEG-DASH ✓ CMAF

  83. HTTP LIVE STREAMING (HLS)

  84. VIDEO.MP4 STREAM.M3U8 STREAM_01.TS STREAM_02.TS STREAM_03.TS ENCODING & PACKAGING VIDEO: H264

    AUDIO: AAC
  85. #EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:6 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-PLAYLIST-TYPE:VOD #EXTINF:6.000000, stream_00.ts #EXTINF:6.000000, stream_01.ts #EXTINF:6.000000,

    stream_02.ts #EXTINF:6.000000, stream_03.ts #EXTINF:6.000000, stream_04.ts #EXTINF:6.000000, stream_05.ts #EXTINF:6.000000, stream_06.ts #EXTINF:6.000000, stream_07.ts #EXTINF:6.000000, stream_08.ts #EXTINF:6.000000, stream_09.ts #EXTINF:5.280000, stream_010.ts #EXT-X-ENDLIST STREAM.M3U8
  86. PLAYER NEEDS TO SUPPORT HLS

  87. <html> <head> <link href="https://vjs.zencdn.net/7.5.4/video-js.css" rel="stylesheet"> </head> <body> <video id='my-video' class='video-js'

    controls preload='auto' height='640' data- setup='{}'> <source src="/live/stream.m3u8" type="application/vnd.apple.mpegurl"> </video> <script src='https://vjs.zencdn.net/7.5.4/video.js'></script> </body> </html>
  88. LIVE ✓ LOW LATENCY ✓ CONSTANT PLAYLIST UPDATES ✓ LOW

    TTL ON PLAYLISTS ✓ ONLY THE LAST X SEGMENTS ARE REQUIRED ✓ SEGMENT SIZE TRADEOFF
  89. VOD ✓ NO PLAYLIST UPDATES ✓ HIGH TTL ON PLAYLISTS

    ✓ ALL SEGMENTS ARE REQUIRED ✓ STORAGE REQUIREMENTS ✓ PRE-FETCHING POSSIBLE
  90. MORE VIDEO FEATURES ✓ GEOIP ✓ DIGITAL RIGHTS MANAGEMENT ✓

    AUTHENTIATION ✓ THROTTLING & RATE LIMITING ✓ ADAPTIVE BITRATE FILTERING ✓ NO MORE ORIGIN
  91. vcl 4.1; import http; import std; backend default { .host

    = "origin"; .port = "80"; } sub vcl_recv { if (req.url ~ "^/vod/.+\.ts$") { http.init(0); http.req_set_max_loops(0,1); http.req_copy_headers(0); http.req_set_method(0, "HEAD"); set req.http.x-next-url = http.prefetch_next_url(); std.log("Prefetching " + req.http.x-next-url); http.req_set_url(0, req.http.x-next-url); http.req_send_and_finish(0); } }
  92. vcl 4.1; import file; sub vcl_init { new root =

    file.init("/var/www/html/"); } sub vcl_backend_fetch { set bereq.backend = root.backend(); } sub vcl_backend_response { if(bereq.url ~ "^/live/stream_[0-9]+\.m3u8$" || bereq.url == "/live/master.m3u8") { set beresp.grace = 0s; set beresp.ttl = 1s; } }
  93. CACHING THE UNCACHEABLE

  94. STATE

  95. COOKIES

  96. sub vcl_recv { if (req.http.Authorization || req.http.Cookie) { /* Not

    cacheable by default */ return (pass); } }
  97. sub vcl_backend_response { if (bereq.uncacheable) { return (deliver); } else

    if (beresp.ttl <= 0s || beresp.http.Set-Cookie || beresp.http.Surrogate-control ~ "(?i)no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "(?i:no-cache|no-store|private)") || beresp.http.Vary == "*") { # Mark as "Hit-For-Miss" for the next 2 minutes set beresp.ttl = 120s; set beresp.uncacheable = true; } return (deliver); }
  98. TAKE IT OR LEAVE IT SITUATION

  99. PLACEHOLDERS

  100. CACHING THE UNCACHEABLE

  101. ORIGIN VARNISH SESSION STORE EXPOSE TEMPLATE PARSE & CACHE TEMPLATE

    FETCH DATA FROM SESION STORE RETURN PERSONALIZED OUTPUT
  102. <h1>Welcome {{ name }}</h1> You have <em>{{ shopping-cart-items }}</em> items

    in your shopping cart Contains session data
  103. _sf2_attributes|a:2:{s:4:"name";s:11:"Thijs Feryn";s:19:"shopping- cart-items";i:6;}_sf2_meta|a:3:{s:1:"u";i:1558952585;s:1:"c";i: 1558952585;s:1:"l";s:1:"0";} PHP serialized session data

  104. vcl 4.1; import cookieplus; import memcached; import edgestash; backend default

    { .host = "origin"; .port = "80"; } sub vcl_init { memcached.servers("--SERVER=memcached:11211"); } sub vcl_recv { if(cookieplus.get("PHPSESSID") !~ "[a-z0-9]+") { return(pass); } return(hash); } sub vcl_backend_response { if (req.url == "/") { edgestash.parse_response(); } if(cookieplus.setcookie_get("PHPSESSID") ~ "[a-z0-9]+") { set beresp.http.x-session-id = cookieplus.setcookie_get("PHPSESSID"); cookieplus.setcookie_delete("PHPSESSID"); } }
  105. sub vcl_deliver { if (edgestash.is_edgestash() && req.url == "/") {

    set resp.http.x-session-raw = memcached.get("sf2s" + cookieplus.get("PHPSESSID", "")); set resp.http.x-session-base = regsuball(resp.http.x-session-raw,"_sf2_attributes\|a:[0-9]+:\{",""); set resp.http.x-session-base = regsuball(resp.http.x-session-base,";}_sf2_meta\|a:.+",""); set resp.http.x-name = regsuball(resp.http.x-session-base,"^([^;]+;)*s:4:\x22name\x22;s:[0-9]+: \x22([^\x22]+)\x22.+$","\2"); set resp.http.x-shopping-cart-items = regsuball(resp.http.x-session-base,"^([^;]+;)*s:19:\x22shopping-cart- items\x22;i:([0-9]+).*$","\2"); edgestash.add_json({" { "name": ""} + resp.http.x-name + {"", "shopping-cart-items": ""} + resp.http.x-shopping-cart-items + {"" } "}); edgestash.execute(); unset resp.http.x-session-raw; unset resp.http.x-session-base; unset resp.http.x-name; unset resp.http.x-shopping-cart-items; if(resp.http.x-session-id ~ "[a-z0-9]+") { cookieplus.setcookie_add("PHPSESSID", resp.http.x-session-id, 30d, req.http.Host, "/"); cookieplus.setcookie_write(); unset resp.http.x-session-id; } } }
  106. <h1>Welcome Thijs Feryn</h1> You have <em>6</em> items in your shopping

    cart END RESULT
  107. FANCY REDIS?

  108. import redis; sub vcl_init { new db = redis.db( location="redis:6379",

    type=master, connection_timeout=500, shared_connections=false, max_connections=1); } sub vcl_deliver { db.command("GET"); db.push("sf_s" + cookieplus.get("PHPSESSID")); db.execute(); set resp.http.x-session-raw = db.get_reply(); set resp.http.x-session-base = regsuball(resp.http.x-session-raw,"_sf2_attributes\|a: [0-9]+:\{",""); set resp.http.x-session-base = regsuball(resp.http.x-session-base,";}_sf2_meta\|a:. +",""); .... }
  109. Link: </build/app.css>; rel=prefetch Pre-fetch CSS file

  110. vcl 4.0; import http; sub vcl_recv { // Store Varnish's

    local address for later use set req.http.X-prefetch = http.varnish_url("/"); } sub vcl_backend_response { if (beresp.http.Link ~ "<.+>.*(prefetch|next)") { // Pull out the Link URL set bereq.http.X-link = regsub(beresp.http.Link, "^.*<([^>]*)>.*$", "\1"); set bereq.http.X-prefetch = regsub(bereq.http.X-prefetch, "/$", bereq.http.X-link); // Prefetch the Link URL back thru Varnish http.init(0); http.req_copy_headers(0); http.req_set_url(0, bereq.http.X-prefetch); http.req_send_and_finish(0); } }
  111. vcl 4.0; import xbody; sub vcl_backend_response { xbody.regsub("www.example.com", "test.example.com"); xbody.regsub("admin@example.com",

    "dev@test.example.com"); } Body replacements
  112. •Accept •Akamai connector •Body access & transformation •Cookieplus •Device atlas

    •Edgestash •File •Geolocation •HTTP communication •JSON parser •Key-value store •Synthetic backends •Encryption •Rate limiting •Throttling •Xkey •Abtest •Authentication •Cookie •Digest •DNS •I18n •LDAP •LUA •Memcached •Redis •OTP •SOAP •UUID
  113. None
  114. VARNISH ENTERPRISE ✓ CLIENT SSL TERMINATION ✓ BACKEND SSL CONNECTIONS

    ✓ PARALLEL ESI ✓ MASSIVE STORAGE ENGINE ✓ ENCRYPTION ✓ THROTTLING ✓ RATE LIMITING ✓ PREFETCHING ✓ GEOLOCATION ✓ AUTHENTICATION ✓ EDGESTASH ✓ CUSTOM STATISTICS ✓ ADMIN MODULE ✓ SUPPORT ✓ HIGH AVAILABILITY ✓ MOBILE APP
  115. HTTPS://AWS.AMAZON.COM/QUICKSTART/ARCHITECTURE/VARNISH/

  116. None
  117. None
  118. HTTPS://FERYN.EU HTTPS://TWITTER.COM/THIJSFERYN HTTPS://INSTAGRAM.COM/THIJSFERYN