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

't Oncachebare cachen

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.

Thijs Feryn

December 10, 2019
Tweet

More Decks by Thijs Feryn

Other Decks in Technology

Transcript

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

    OOK DEEL UUT VAN DE USER EXPERIENCE
  2. 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
  3. 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
  4. 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
  5. vcl 4.1; import cookieplus; sub vcl_recv { cookieplus.keep("language"); cookieplus.write(); }

    sub vcl_hash { hash_data(cookieplus.get("language")); } VMOD_COOKIE
  6. ✓CLIENT-SIDE ✓WE KEN' DA ✓PARALLEL VERWERKT ✓GRACEFUL DEGRADATION -DE BROWSER

    MOET ER Z'N PLAN MEE TREKN -EXTRA ROUNDTRIPS -BITJE TRAGER AJAX
  7. ESI ✓ PLACEHOLDER ✓ VERWERKT DEUR VARNISH ✓ OUTPUT IS

    EEN COMPOSITIE VAN BLOCKS ✓ STATE PER BLOCK ✓ TTL PER BLOCK
  8. 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; } }
  9. ✓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
  10. 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
  11. 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
  12. 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
  13. JE ZIET ER VET MEE ✓ AJAX CALL ✓ LADEN

    VIA ESI EN VERWERKEN VIA LOKALE JAVASCRIPT ✓ EDGESTASH
  14. 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
  15. 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
  16. {{ edgestash('#username', '/session') }} Welcome {{ edgestash('username') }} {{ edgestash('/username')

    }} {{ edgestash('^username') }} Welcome guest {{ edgestash('/username') }