Accelerating OTT video platforms with Varnish - London Video Tech meetup 2020

Ca901ddcea38854b9783781c91fc87c9?s=47 Thijs Feryn
February 04, 2020

Accelerating OTT video platforms with Varnish - London Video Tech meetup 2020

Slides for my OTT video acceleration talk at the London Video Technology meetup February 2020 edition: https://feryn.eu/speaking/accelerating-ott-video-platforms-varnish-london-video-technology-meetup-2020/

Ca901ddcea38854b9783781c91fc87c9?s=128

Thijs Feryn

February 04, 2020
Tweet

Transcript

  1. 4.
  2. 13.
  3. 17.
  4. 18.
  5. 20.
  6. 22.
  7. 24.
  8. 26.
  9. 27.
  10. 30.
  11. 37.

    WHY IS VARNISH SO POWERFUL? ✓ EXTREMELY LOW RESOURCE ✓

    EXTREMELY STABLE ✓ 100 GBIT PER SERVER ✓ REQUEST COALESCING ✓ VARNISH CONFIGURATION LANGUAGE ✓ VMODS ✓ COMPLIES TO HTTP BEST PRACTICES
  12. 41.

    vcl 4.1; backend default { .host = "origin"; .port =

    "80"; } sub vcl_backend_response { if(bereq.url == "/vod/master.m3u8" ){ set beresp.grace = 1h; } }
  13. 43.
  14. 44.
  15. 45.

    vcl 4.1; backend origin { .host = "1.2.3.4"; .port =

    "80"; } sub vcl_recv { if(req.url ~ "^/(live|vod)/") { unset req.http.authorization; unset req.http.cookie; } } sub vcl_backend_response { if(bereq.url ~ "^/(live|vod)/") { unset beresp.http.set-cookie; set beresp.grace = 5s; } if(bereq.url ~ "^/live/.*\.m3u8") { set beresp.ttl = 1ms; } if(bereq.url ~ "^/vod/.*\.m3u8") { set beresp.ttl = 3600s; } }
  16. 47.

    LIVE ✓ LOW LATENCY ✓ CONSTANT PLAYLIST UPDATES ✓ LOW

    TTL ON PLAYLISTS ✓ ONLY THE LAST X SEGMENTS ARE REQUIRED ✓ SEGMENT SIZE TRADEOFF
  17. 48.

    VOD ✓ NO PLAYLIST UPDATES ✓ HIGH TTL ON PLAYLISTS

    ✓ PRE-FETCHING POSSIBLE ✓ ALL SEGMENTS ARE REQUIRED ✓ STORAGE REQUIREMENTS
  18. 49.
  19. 51.

    WHERE VARNISH STORES ITS OBJECTS ✓ MEMORY ✓ DISK ✓

    MASSIVE STORAGE ENGINE (ENTERPRISE ONLY)
  20. 52.

    MSE ✓ MIX OF MEMORY AND DISK ✓ SMARTER LRU

    ✓ PRE-ALLOCATED LARGE FILES ON DISK ✓ LESS DISK FRAGMENTATION ✓ INTELLIGENT STORAGE ROUTING
  21. 54.

    env: { id = "myenv"; memcache_size = "100G"; books =

    ( { id = "book1"; directory = "/var/lib/mse/book1"; database_size = "1G"; stores = ( { id = "store-1-1"; filename = "/var/lib/mse/stores/disk1/store-1-1.dat"; size = "2T"; tags = ( "slow", "sata" ); }, { tags = ( "fast", "ssd" ); id = "store-1-2"; filename = "/var/lib/mse/stores/disk2/store-1-2.dat"; size = "500G"; } ); }); default_stores = "none"; }; MSE.CONF
  22. 59.

    vcl 4.1; import mse; sub vcl_backend_response { if (beresp.ttl <

    120s) { mse.set_stores("none"); } else { if (beresp.http.Transfer-Encoding ~ "chunked" || beresp.http.Content-Length > 1M) { mse.set_stores("sata"); } else { mse.set_stores("fast"); } } }
  23. 65.

    vcl 4.1; backend default { .host = "1.2.3.4"; .port =

    "80"; } sub vcl_recv { if(req.url ~ "^/live/enc.key") { if (req.http.Authorization != "Basic YWRtaW46YWRtaW4=") { return (synth(401, "Restricted")); } } unset req.http.Authorization; } sub vcl_synth { if (resp.status == 401) { set resp.http.WWW-Authenticate = {"Basic realm="Restricted area""}; } }
  24. 67.

    vcl 4.1; import cookieplus; import redis; import kvstore; backend default

    { .host = "origin"; .port = "80"; } sub vcl_init { new authorized_sessions = kvstore.init(); new db = redis.db( location="redis:6379", type=master, connection_timeout=500, shared_connections=false, max_connections=1); }
  25. 68.

    sub vcl_recv { if(req.url ~ "^/live/enc.key") { if(authorized_sessions.get(cookieplus.get("PHPSESSID"),"empty") == "empty")

    { db.command("GET"); db.push("PHPREDIS_SESSION:"+cookieplus.get("PHPSESSID")); db.execute(); if(db.get_string_reply() !~ "authorized\|b\:1\;") { authorized_sessions.set(cookieplus.get("PHPSESSID"),"false"); return (synth(401, "Not Authorized")); } else { authorized_sessions.set(cookieplus.get("PHPSESSID"),"true", 10s); } } elseif(authorized_sessions.get(cookieplus.get("PHPSESSID")) == "false") { return (synth(401, "Not Authorized")); } } }
  26. 70.

    vcl 4.1; import mmdb; backend default { .host = "192.0.2.11";

    .port = "8080"; } # create a database object sub vcl_init { new geodb = mmdb.init("/path/to/db"); } sub vcl_recv { # retrieve the name of the request's origin set req.http.Country-Name = geodb.country_name(client.ip); # if the country doesn't come from Germany or Belgium, deny access if (req.http.Country-Name != "Germany" || req.http.Country-Name != "Belgium") { return (synth(403, "Sorry, only available in Germany and Belgium")); } } Geo blocking
  27. 71.

    vcl 4.1; import geodirector; import mmdb; backend us { .host

    = "us.example.com"; .port = "80"; } backend uk { .host = "uk.example.com"; .port = "80"; } backend be { .host = "be.example.com"; .port = "80"; } sub vcl_init { new geodb = mmdb.init("/path/to/db"); }
  28. 72.

    sub vcl_recv { set req.http.Country-Code = geodb.country_code(client.ip); if(req.http.Country-Code == "US")

    { set req.backend_hint = us; } elseif(req.http.Country-Code == "GB") { set req.backend_hint = uk; } else { set req.backend_hint = be; } } Geo backend selection
  29. 74.

    vcl 4.1; import file; backend default { .host = "origin";

    .port = "80"; } sub vcl_init { new root = file.init("/var/www/html/"); } sub vcl_backend_fetch { set bereq.backend = root.backend(); }
  30. 76.

    vcl 4.1; import http; 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(); http.req_set_url(0, req.http.x-next-url); http.req_send_and_finish(0); } }
  31. 78.

    vcl 4.1; import vsthrottle; import tcp; backend default { .host

    = "origin"; .port = "80"; } sub vcl_recv { if (vsthrottle.is_denied(client.identity, 15, 10s, 60s)) { # Client has exceeded 15 reqs per 10s or get blocked for 60s return (synth(429, "Too Many Requests")); } # Download at 1 MB/s tcp.set_socket_pace(1000); }
  32. 79.
  33. 80.
  34. 83.
  35. 84.