going crazy with varnish and symfony

31
Going crazy with Symfony and Varnish David de Boer 15 May 2015

Upload: david-de-boer

Post on 05-Aug-2015

58 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Going crazy with Varnish and Symfony

Going crazy with Symfony and Varnish

David de Boer15 May 2015

Page 2: Going crazy with Varnish and Symfony

Varnish

Public content

Most requested

Most processing

Static assets

Authenticated content?

$ varnishtop -i BeReqUrl

Page 3: Going crazy with Varnish and Symfony

Leiden

Driebit, Amsterdam

FOSHttpCache FOSHttpCacheBundle

Page 4: Going crazy with Varnish and Symfony

Break up

Page 5: Going crazy with Varnish and Symfony

only one TTL

Page 6: Going crazy with Varnish and Symfony

don’t cache

15 mins

1 hour

24 hours

Page 7: Going crazy with Varnish and Symfony
Page 8: Going crazy with Varnish and Symfony

Enable ESI sub vcl_recv { set req.http.Surrogate-Capability = "abc=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; }}

Page 9: Going crazy with Varnish and Symfony

Plain PHP<?phpheader('Surrogate-Control: ESI/1.0');?><html><body> <esi:include src="/blue.php" /> Your main content. <esi:include src="/red.php" /></body></html>

<?php// blue.phpheader('Cache-Control: no-cache');?>Blue is not cached.

<?php// red.phpheader('Cache-Control: s-maxage=3600');?>Red is cached for an hour.

Page 10: Going crazy with Varnish and Symfony

ESI in Symfony# app/config/config.yml

framework: esi: enabled: true fragments: { path: /_fragment }

{# template.twig #}

{{ render_esi(controller('AppBundle:Red:list', {'max': 100})) }}

Page 11: Going crazy with Varnish and Symfony

ESI performance<?php// blue.php

sleep(2);header('Cache-Control: no-cache');?>

Blue is kind of sleepy.

<?php// red.php

sleep(5);header('Cache-Control: no-cache');?>

And red even more so.

7 seconds

Page 12: Going crazy with Varnish and Symfony
Page 13: Going crazy with Varnish and Symfony

Client-side

Rich JavaScript apps

JSON data through Ajax

API design

Page 14: Going crazy with Varnish and Symfony

ESI in JSONvarnishd -p esi_syntax=0x00000003

{ "id": 1, "name": "Martian Ambassador", "_embedded": { "category": <esi:include src="/categories/1"/> }}

Page 15: Going crazy with Varnish and Symfony

Invalidation<?php

use FOS\HttpCache\ProxyClient\Varnish;use FOS\HttpCache\CacheInvalidator;

$varnishClient = new Varnish('127.0.0.1', 'http://mars-attacks.dev');$cacheInvalidator = new CacheInvalidator($varnishClient);

// If some data changes in your app:$cacheInvalidator->invalidatePath('/red.php')->flush();

Page 16: Going crazy with Varnish and Symfony

Invalidation# app/config/config.ymlfos_http_cache: proxy_client: varnish: servers: 127.0.0.1 base_url: mars-attacks.dev

<?php

use FOS\HttpCacheBundle\Configuration\InvalidateRoute;

/** * @InvalidateRoute("red")*/public function editAction($id){ // This is where data changes}

Page 17: Going crazy with Varnish and Symfony
Page 18: Going crazy with Varnish and Symfony

Individual caching?// builtin.vcl

sub vcl_recv { // ... if (req.http.Authorization || req.http.Cookie) { /* Not cacheable by default */ return (pass); } // ...}

Page 19: Going crazy with Varnish and Symfony

Individual caching?sub vcl_recv { // ... if (req.http.Authorization || req.http.Cookie) { /* Cache all the personal things! */ return (hash); } // ...}

Page 20: Going crazy with Varnish and Symfony
Page 21: Going crazy with Varnish and Symfony

Individual caching?sub vcl_recv { // ... if (req.http.Authorization || req.http.Cookie) { /* Cache all the personal things! */ return (hash); } // ...}

sub vcl_deliver { // ... set resp.http.Vary = "Cookie,Authorization"; }

Page 22: Going crazy with Varnish and Symfony

Group together

Page 23: Going crazy with Varnish and Symfony

User context

Varnish

hash lookup

vary on credentials#

content request

vary on hash header

#

App ⟳

Page 24: Going crazy with Varnish and Symfony

Varnish

User contexthash lookup

vary on credentials#

content request

vary on hash header

#

Page 25: Going crazy with Varnish and Symfony

Varnish

User context

##

#

##

#

# ##

##

#

#

##

#

#

#

#

#

#

##

#

#

##

# # #

Page 26: Going crazy with Varnish and Symfony

Configure user contextsub vcl_recv { if (req.restarts == 0 && (req.http.cookie || req.http.authorization) && (req.method == "GET" || req.method == "HEAD") ) { if (req.http.accept) { set req.http.X-Fos-Original-Accept = req.http.accept; } set req.http.accept = "application/vnd.fos.user-context-hash"; set req.http.X-Fos-Original-Url = req.url; set req.url = "/_fos_user_context_hash";

return (hash); }

if (req.restarts > 0 && req.http.accept == "application/vnd.fos.user-context-hash" ) { set req.url = req.http.X-Fos-Original-Url; unset req.http.X-Fos-Original-Url; if (req.http.X-Fos-Original-Accept) { set req.http.accept = req.http.X-Fos-Original-Accept; unset req.http.X-Fos-Original-Accept; } else { unset req.http.accept; }

return (hash); }}

Page 27: Going crazy with Varnish and Symfony

Configure user contextsub vcl_backend_response { if (bereq.http.accept ~ "application/vnd.fos.user-context-hash" && beresp.status >= 500 ) { return (abandon); }}

sub vcl_deliver { if (req.restarts == 0 && resp.http.content-type ~ "application/vnd.fos.user-context-hash" ) { set req.http.X-User-Context-Hash = resp.http.X-User-Context-Hash;

return (restart); }

set resp.http.Vary = regsub(resp.http.Vary, "(?i),? *X-User-Context-Hash *", ""); set resp.http.Vary = regsub(resp.http.Vary, "^, *", ""); if (resp.http.Vary == "") { unset resp.http.Vary; }

unset resp.http.X-User-Context-Hash;}

Page 28: Going crazy with Varnish and Symfony

Cleaning cookies$ varnishlog -c -i ReqHeader -I CookieCookie: __uvt=;PHPSESSID=ht8rl2tnbikpeoau7q5g677125;_ga=GA1.2.1332615739.14⏎

31368832;uvts=320PnWhzN5bW7V2D

sub vcl_recv { set req.http.cookie = ";" + req.http.cookie; set req.http.cookie = regsuball(req.http.cookie, "; +", ";"); set req.http.cookie = regsuball(req.http.cookie, ";(PHPSESSID)=", "; \1="); set req.http.cookie = regsuball(req.http.cookie, ";[^ ][^;]*", ""); set req.http.cookie = regsuball(req.http.cookie, "^[; ]+|[; ]+$", "");}

Cookie: PHPSESSID=ht8rl2tnbikpeoau7q5g677125

Page 29: Going crazy with Varnish and Symfony

FOSHttpCacheBundle# app/config/config.yml fos_http_cache: user_context: hash_cache_ttl: 3600 hash_header: "Custom-User-Hash-Header" role_provider: true

Page 30: Going crazy with Varnish and Symfony

Custom provider<?php

use FOS\HttpCache\UserContext\ContextProviderInterface;use FOS\HttpCache\UserContext\UserContext;

class IsAwesomeProvider implements ContextProviderInterface{ private $userService;

public function __construct(YourUserService $userService) { $this->userService = $userService; }

public function updateUserContext(UserContext $userContext) { $userContext->addParameter('awesome', $this->userService->isAwesome()); }}

// <service id="app_bundle.provider" class="AppBundle\Provider\IsAwesomeProvider"> <tag name="fos_http_cache.user_context_provider" /></service>

Page 31: Going crazy with Varnish and Symfony

Thanks!

[email protected] @ddeboer_nl

FOSHttpCacheFOSHttpCacheBundle

https://joind.in/14546