't Oncachebare cachen

Ca901ddcea38854b9783781c91fc87c9?s=47 Thijs Feryn
December 10, 2019

't Oncachebare cachen

A talk about caching personalized data in Varnish, presented at the december 2019 edition of the PHPWVL meetup.

This presentation was delivered in the local dialect of the area. The slides are also in that dialect.

See https://feryn.eu/speaking/t-oncachebare-cachen/ for more information about this presentation.

Ca901ddcea38854b9783781c91fc87c9?s=128

Thijs Feryn

December 10, 2019
Tweet

Transcript

  1. 'T ONCACHEBARE CACHEN DOOR THIJS FERYN MET VARNISH

  2. Trage websites SUCKN

  3. DE MENSCHN EN GÈREN DAT RAPT GOAT EN DAT MAKT

    OOK DEEL UUT VAN DE USER EXPERIENCE
  4. TRAGE EN PLAT IS VERRE 'T ZELFSTE

  5. None
  6. None
  7. None
  8. MET SERVERS SMIETEN

  9. MO' MONEY MO' SERVERS MO' PROBLEMS WITJEWEL KÈREL

  10. EFTJES KI KIEKEN NO DE TRAAGSTE DELEN

  11. OPTIMALISEREN

  12. ACHTER EEN ENDE KOM JE TENDN

  13. CACHE

  14. HEY, IK ZIEN THIJS

  15. None
  16. None
  17. None
  18. IK ZIEN EVANHELIST BIE

  19. None
  20. None
  21. None
  22. 4,800,000 WEBSITES 19% VAN DE TOP 10K WEBSITES

  23. None
  24. IK ZIEN @THIJSFERYN

  25. None
  26. None
  27. NORMAAL GEBRUKER SERVER

  28. MET VARNISH GEBRUKER VARNISH SERVER

  29. None
  30. None
  31. DE CACHE CONTROLEREN 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 Vary: Accept-Language
  32. STATE

  33. STATE ~ HEBRUKERSSPECIFIEKE DATA COOKIES AUTH HEADERS

  34. 'T IS JUSTE VOE JOEN EN NIEMAND ANDERS NIET GECACHED

    EJT VERSTOAN?
  35. VARNISH CONFIGURATION LANGUAGE

  36. vcl 4.1; 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); } } } OLENE EEN PAAR COOKIES OEDEN
  37. 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 VARIATIE
  38. vcl 4.1; import cookieplus; sub vcl_recv { cookieplus.keep("language"); cookieplus.write(); }

    sub vcl_hash { hash_data(cookieplus.get("language")); } VMOD_COOKIE
  39. BEVAT HEBRUKERSHEHEVENS

  40. NIET CACHEN

  41. PLACEHOLDERS

  42. APARTE HTTP REQUEST

  43. AJAX

  44. ✓CLIENT-SIDE ✓WE KEN' DA ✓PARALLEL VERWERKT ✓GRACEFUL DEGRADATION -DE BROWSER

    MOET ER Z'N PLAN MEE TREKN -EXTRA ROUNDTRIPS -BITJE TRAGER AJAX
  45. EDGE-SIDE INCLUDES ESI

  46. <esi:include src="/header" />

  47. ESI ✓ PLACEHOLDER ✓ VERWERKT DEUR VARNISH ✓ OUTPUT IS

    EEN COMPOSITIE VAN BLOCKS ✓ STATE PER BLOCK ✓ TTL PER BLOCK
  48. sub vcl_recv { set req.http.Surrogate-Capability = "key=ESI/1.0"; } sub vcl_backend_response

    { if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } }
  49. ✓SERVER-SIDE ✓GESTANDAARDISEERD ✓VERWERKT ON THE “EDGE”, NIET IN DE BROWSER

    ✓IN 'T ALHEMEEN RAPPER -SEQUENTIEEL* -EEN DERAN, OL DERAN -BEPERKTE IMPLEMENTATIE IN VARNISH -WE KENNEN DA NIE ZO GOED ESI PARALLEL IN ENTERPRISE
  50. NIET-CACHEBARE ROUTES ZIEN NOG OSSAN EEN TERE PLEKKE

  51. NIET ZOMAAR EEN CACHE NIET ZOMAAR "TE NEMEN OF TE

    LATEN"
  52. EEN HTTP BLOKKENDOZE

  53. BESLISSINGEN PAKKEN "ON THE EDGE"

  54. vcl 4.1; import cookieplus; import redis; import synthbackend; sub vcl_init

    { new db = redis.db( location="redis:6379", type=master, connection_timeout=500, shared_connections=false, max_connections=1); } sub vcl_recv { set req.http.X-Login = "false"; set req.http.x-session = cookieplus.get("PHPSESSID","guest"); if(req.http.x-session != "guest") { db.command("EXISTS"); db.push("sf_s"+cookieplus.get("PHPSESSID")); db.execute(); if(db.get_integer_reply() == 1) { set req.http.X-Login = "true"; } } } SYNTHETIC HTTP
  55. sub vcl_backend_fetch { if(bereq.url == "/session") { if(bereq.http.X-Login != "true")

    { set bereq.backend = synthbackend.from_string("{}"); return(fetch); } db.command("EVAL"); db.push({" local session = redis.call('GET', KEYS[1]) if session == nil then return '{}' end local result = string.gsub(session, '[%c]', '') local username = string.gsub(result,'.+Userusername\";s:[0-9]+:\"([^\"]+)\";.+','%1') if username == nil then return '{}' end return '{"username":"'.. username ..'"}' "}); db.push(1); db.push("sf_s"+cookieplus.get("PHPSESSID")); db.execute(); set bereq.backend = synthbackend.from_string(db.get_string_reply()); } } sub vcl_backend_response { if(bereq.url == "/session") { set beresp.http.Content-Type = "application/json; charset=utf-8"; set beresp.ttl = 3600s; set beresp.http.vary = "x-session"; } } REDIS LUA CODE
  56. GEBRUKER GET /session Cookie: PHPSESSID=7er3hjKal8u235c87u6ih0vz8Y HTTP/1.1 200 OK Content-Length: 31

    Content-Type: application/json; charset=utf-8 X-Varnish: 163854 196622 Age: 27 {"username":"thijs"} VARNISH
  57. JE ZIET ER VET MEE ✓ AJAX CALL ✓ LADEN

    VIA ESI EN VERWERKEN VIA LOKALE JAVASCRIPT ✓ EDGESTASH
  58. {{ EDGESTASH }} VARNISH MODULE DIE MUSTACHE SYNTAX VERWERKT "ON

    THE EDGE"
  59. vcl 4.1; import edgestash; backend default { .host = "1.1.1.1";

    .port = "80"; } sub vcl_backend_response { if (bereq.url == "/session") { edgestash.index_json(); } else if (bereq.url == "/") { edgestash.parse_response(); } } sub vcl_deliver { if (req.url == "/" && edgestash.is_edgestash()) { edgestash.add_json_url("/session"); edgestash.execute(); } } EDGESTASH
  60. EDGESTASH {"username":"Thijs"} <div>{{ username }}</div> <div>Thijs</div>

  61. BITJE MEER FLEXIBILITEIT

  62. Surrogate-Control: edgestash="EDGESTASH/2.1" Link: </session>; rel=edgestash

  63. vcl 4.1; import edgestash; import std; backend default { .host

    = "1.1.1.1"; } sub vcl_recv { set req.http.Surrogate-Capability={"edgestash="EDGESTASH/2.1""}; } sub vcl_backend_response { if(beresp.http.Link) { std.collect(beresp.http.Link,","); } if(beresp.http.Link ~ "<([^>]+)>; rel=edgestash") { set beresp.http.x-edgestash-json-urls = regsuball(beresp.http.Link,"(?(?=<[^>]+>; rel=edgestash)<([^>]+)>; rel=edgestash|<([^>]+)>; rel=[a-z]+, )","\1"); } if(beresp.http.Surrogate-Control) { std.collect(beresp.http.Surrogate-Control); } if(beresp.http.Surrogate-Control ~ {".*="EDGESTASH/2\.[0-9]+".*"}) { edgestash.parse_response(); } } EDGESTASH
  64. sub vcl_deliver { if(edgestash.is_edgestash() && resp.http.x-edgestash-json-urls) { edgestash.add_json_url_csv(resp.http.x-edgestash-json-urls); edgestash.execute(); }

    unset resp.http.Link; unset resp.http.x-edgestash-json-urls; unset resp.http.surrogate-control; } EDGESTASH
  65. None
  66. COMPOSER REQUIRE THIJSFERYN/EDGESTASH-TWIG-BUNDLE

  67. <div>{{ edgestash('username','/session') }}</div> <div>{{ username | edgestash('username','/session') }}</div>

  68. <div> {% if isEdgestash() %} //Edgestash-supported logic {% else %}

    //Regular Twig logic {% endif %} </div>
  69. {{ edgestash('#username', '/session') }} Welcome {{ edgestash('username') }} {{ edgestash('/username')

    }} {{ edgestash('^username') }} Welcome guest {{ edgestash('/username') }
  70. <ul> {{ edgestash('#.', '/users') }} <li>{{ edgestash('username') }}</li> {{ edgestash('/.')

    }} </ul>
  71. None
  72. VANAF $0.20/TER EURE + 14 DAGEN VOE NIET

  73. None
  74. None
  75. HTTPS://FERYN.EU HTTPS://TWITTER.COM/THIJSFERYN HTTPS://INSTAGRAM.COM/THIJSFERYN