Nice performance using SF2 cache wrapping sf1 application Marc Weistroff \ Emmanuel Cohen Sf Live \ SF 2011 Thursday, March 3 2011
Who we are Emmanuel Cohen Project manager at Sensio Labs 4 year experience with PHP5 5+ year experience with Java EE Learned Basic on Amstrad CPC 6128
Who we are Marc Weistroff Developer at Sensio Labs since 11/2009 Lead developer on this project Experiences with C, and PHP from version 3 Encountered programming with Amos Basic on Amiga 500
This talk Symfony2 symfony 1 HTTP Cache Edge Side Includes (ESI) Web architecture Online media
Our client L’Express Magazine  Express-Roularta Group Magazine created in 1953 http://www.lexpress.fr Top 3 French online news Need for speed!
 
 
 
The project A cultural knowledge base A bridge between hot news and cultural knowledge An extension of www.lexpress.fr
 
 
Technical objectives Performance A full scale Proof-of-Concept for the future Keep it Simple
Constraints Heterogeneous XML Sources Solution based on symfony 1 Adaptability (for future extensions)
How does this app work ?
Our symfony 1 application design HTML Renderer XML Server OCARI Culture OCARI Content Stores Normalizes Aggregates Serves XML Sources deliver heterogeneous data Renders HTML with XSL Renders static layouts
Our symfony 1 application design Highly specialized applications Loose coupling Front dedicated to delivering content fast
Addressing performance  with Symfony2
Addressing performance with Sf2 With Symfony2  built-in Gateway  : HTTP cache ESI : Edge Side Includes
Performance with Symfony2 : HTTP Cache HTTP  RFC http://tools.ietf.org/wg/httpbis/ http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12
Performance with Symfony2 : HTTP Cache Symfony2 uses HTTP cache headers to handle cache s-maxage or max-age Etag, Last-Modified, If-Modified-Since http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12
Performance with Symfony2 : HTTP Cache symfony 1  Applicative cache Symfony2  Light-weight HttpKernel The application is not hit Supports a standard
Find out what’s stale  The problem of invalidation Performance with Symfony2: Cache issues
Selective caching Do not regenerate the whole page when you just need to regenerate small parts of it Performance with Symfony2: Cache issues
Performance with Symfony2: ESI Edge-Side include: A markup language W3C note from Akamai http:// www.w3.org/TR/esi-lang http:// www.akamai.com/html/support/esi.html
ESI : A page in lexpress.fr
Performance with Symfony2: ESI Each fragment has its own ttl or validation rule  => the fragments are selectively refreshed
Performance with Symfony2: ESI Dependance is defined once and for all In expiration: simply set your ttl for each fragment
How does ESI work?
Performance with Symfony2: ESI Represented by an HTML Tag <esi:include src=“/movie/dogma/critics” /> Processed by a proxy Transformed into HTTP Request to the application Response is inserted in place of the esi tag HTTP cache is handled independently for each esi tag
/movie/dogma
/movie/dogma
Html Fragment Pure HTML Inserted in lieu of the <esi /> tag No <html>, <body> or <head> tag in this case
What you need Any client! A proxy that handles ESI (ie: Varnish or Symfony2) An application that delivers HTML and HTTP cache headers Serve HTML pages that contain ESI tags
First request ever Client Proxy Application /movie/dogma /movie/dogma miss Cache-Control: s-maxage=600 /movie/dogma/casting /movie/dogma/critics Cache-Control: s-maxage=3600 Cache-Control: s-maxage=300
Request at t+200 Client Proxy Application /movie/dogma hit
The application is never hit! As if the complete page was cached in the reverse proxy
Request at t+500 Client Proxy Application /movie/dogma /movie/dogma/critics Cache-Control: s-maxage=300 hit
The application is partially hit And has to build only a small fragment of the page
Pros You use HTTP cache, not the application one. Performance improvements! Granularity: Different cache strategy or TTL on different parts of your page
Cons Your app will be hit n times upon the very first request Your app have to be designed to support the rendering of fragments
But our app is symfony 1 right ?
What to do with your symfony 1 application when you are dying to use Symfony2?  Wrap it. Our app is symfony 1
Our symfony 1 application design HTML Renderer XML Server OCARI Culture OCARI Content Symfony1 wrapper Edge side Symfony2 Stores Normalizes Aggregates Serves XML Sources deliver heterogeneous data Renders HTML with XSL Renders static layouts
Wrapping symfony 1 with Symfony2
Constraint We use the Symfony2 ESI/Cache proxy All the call to our app is done in the same PHP process
symfony 1 needs tweaking in order to work around a few obstacles
Which ones ? It is  not reentrant sfConfig singleton sfContext singleton It sends the response directly to the client Filter chain execution At the end, sfRenderingFilter sends the complete response
What about Symfony2? Better architecture: Symfony2 is reentrant Symfony2 is heavily based on interfaces Symfony2 is divided into several components HttpKernel\HttpKernelInterface
HttpKernel\HttpKernelInterface Lightweight (1 method) Forces to implement a “handle” method that accepts a Symfony2 Request object and returns a Symfony2 Response object Used by all the classes that act as a Kernel in Symfony2 (ie: HttpKernel\HttpCache)
Addressing the issues Reentrance Override the super globals Create a fresh new context each time Filter chain Replace sfRenderingFilter by a noRenderingFilter class Create a Symfony2 Response object and returns it
Final app architecture EsiCacheKernel SymfonyWrapperKernel symfony 1 application
https://github.com/marcw/sflive-2011
Then… You have to design your app to serve HTML fragments!
Designing your app Don’t think partials or components, think actions! Actions render HTML fragments Actions MUST define explicitly the response cache headers.
And now where happy
Or are we ?
Our choices The choice of symfony 1 The choice of Symfony2 The choice to mix Expiration over validation
This is symfony1 :  DO NOT TRY ANY OF THIS AT HOME!
Our results It works! The frontend is  scalable  and  extensible Performance is nice, but we needed to improve the Store.php class
What to do next ?
Implementing cache validation The application needs to garantee freshness How to avoid hitting the application ?
Proxy ESI New response Or 304 URL-> {ETag} ETag-> lastmodified If Etag absent or stale Response with HTTP headers Etag LastModified Client Request with HTTP headers If-None-Match If-Modified-Since App New response Or 304 If cache entry is not fresh enough Cache Validation Optimizer
Contact @ L’Express Sébastien Angèle [email_address] Jérôme Macias [email_address]
Questions ? Marc Weistroff @futurecat [email_address] http://www.marcw.net Emmanuel Cohen @emmanuelcohen [email_address]
Thank you! Please rate this talk at http://joind.in/2749

Nice performance using Sf2 cache wrapping Sf1 application - Paris

  • 1.
    Nice performance usingSF2 cache wrapping sf1 application Marc Weistroff \ Emmanuel Cohen Sf Live \ SF 2011 Thursday, March 3 2011
  • 2.
    Who we areEmmanuel Cohen Project manager at Sensio Labs 4 year experience with PHP5 5+ year experience with Java EE Learned Basic on Amstrad CPC 6128
  • 3.
    Who we areMarc Weistroff Developer at Sensio Labs since 11/2009 Lead developer on this project Experiences with C, and PHP from version 3 Encountered programming with Amos Basic on Amiga 500
  • 4.
    This talk Symfony2symfony 1 HTTP Cache Edge Side Includes (ESI) Web architecture Online media
  • 5.
    Our client L’ExpressMagazine Express-Roularta Group Magazine created in 1953 http://www.lexpress.fr Top 3 French online news Need for speed!
  • 6.
  • 7.
  • 8.
  • 9.
    The project Acultural knowledge base A bridge between hot news and cultural knowledge An extension of www.lexpress.fr
  • 10.
  • 11.
  • 12.
    Technical objectives PerformanceA full scale Proof-of-Concept for the future Keep it Simple
  • 13.
    Constraints Heterogeneous XMLSources Solution based on symfony 1 Adaptability (for future extensions)
  • 14.
    How does thisapp work ?
  • 15.
    Our symfony 1application design HTML Renderer XML Server OCARI Culture OCARI Content Stores Normalizes Aggregates Serves XML Sources deliver heterogeneous data Renders HTML with XSL Renders static layouts
  • 16.
    Our symfony 1application design Highly specialized applications Loose coupling Front dedicated to delivering content fast
  • 17.
  • 18.
    Addressing performance withSf2 With Symfony2 built-in Gateway : HTTP cache ESI : Edge Side Includes
  • 19.
    Performance with Symfony2: HTTP Cache HTTP RFC http://tools.ietf.org/wg/httpbis/ http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12
  • 20.
    Performance with Symfony2: HTTP Cache Symfony2 uses HTTP cache headers to handle cache s-maxage or max-age Etag, Last-Modified, If-Modified-Since http://tools.ietf.org/html/draft-ietf-httpbis-p6-cache-12
  • 21.
    Performance with Symfony2: HTTP Cache symfony 1 Applicative cache Symfony2 Light-weight HttpKernel The application is not hit Supports a standard
  • 22.
    Find out what’sstale The problem of invalidation Performance with Symfony2: Cache issues
  • 23.
    Selective caching Donot regenerate the whole page when you just need to regenerate small parts of it Performance with Symfony2: Cache issues
  • 24.
    Performance with Symfony2:ESI Edge-Side include: A markup language W3C note from Akamai http:// www.w3.org/TR/esi-lang http:// www.akamai.com/html/support/esi.html
  • 25.
    ESI : Apage in lexpress.fr
  • 26.
    Performance with Symfony2:ESI Each fragment has its own ttl or validation rule => the fragments are selectively refreshed
  • 27.
    Performance with Symfony2:ESI Dependance is defined once and for all In expiration: simply set your ttl for each fragment
  • 28.
  • 29.
    Performance with Symfony2:ESI Represented by an HTML Tag <esi:include src=“/movie/dogma/critics” /> Processed by a proxy Transformed into HTTP Request to the application Response is inserted in place of the esi tag HTTP cache is handled independently for each esi tag
  • 30.
  • 31.
  • 32.
    Html Fragment PureHTML Inserted in lieu of the <esi /> tag No <html>, <body> or <head> tag in this case
  • 33.
    What you needAny client! A proxy that handles ESI (ie: Varnish or Symfony2) An application that delivers HTML and HTTP cache headers Serve HTML pages that contain ESI tags
  • 34.
    First request everClient Proxy Application /movie/dogma /movie/dogma miss Cache-Control: s-maxage=600 /movie/dogma/casting /movie/dogma/critics Cache-Control: s-maxage=3600 Cache-Control: s-maxage=300
  • 35.
    Request at t+200Client Proxy Application /movie/dogma hit
  • 36.
    The application isnever hit! As if the complete page was cached in the reverse proxy
  • 37.
    Request at t+500Client Proxy Application /movie/dogma /movie/dogma/critics Cache-Control: s-maxage=300 hit
  • 38.
    The application ispartially hit And has to build only a small fragment of the page
  • 39.
    Pros You useHTTP cache, not the application one. Performance improvements! Granularity: Different cache strategy or TTL on different parts of your page
  • 40.
    Cons Your appwill be hit n times upon the very first request Your app have to be designed to support the rendering of fragments
  • 41.
    But our appis symfony 1 right ?
  • 42.
    What to dowith your symfony 1 application when you are dying to use Symfony2? Wrap it. Our app is symfony 1
  • 43.
    Our symfony 1application design HTML Renderer XML Server OCARI Culture OCARI Content Symfony1 wrapper Edge side Symfony2 Stores Normalizes Aggregates Serves XML Sources deliver heterogeneous data Renders HTML with XSL Renders static layouts
  • 44.
    Wrapping symfony 1with Symfony2
  • 45.
    Constraint We usethe Symfony2 ESI/Cache proxy All the call to our app is done in the same PHP process
  • 46.
    symfony 1 needstweaking in order to work around a few obstacles
  • 47.
    Which ones ?It is not reentrant sfConfig singleton sfContext singleton It sends the response directly to the client Filter chain execution At the end, sfRenderingFilter sends the complete response
  • 48.
    What about Symfony2?Better architecture: Symfony2 is reentrant Symfony2 is heavily based on interfaces Symfony2 is divided into several components HttpKernel\HttpKernelInterface
  • 49.
    HttpKernel\HttpKernelInterface Lightweight (1method) Forces to implement a “handle” method that accepts a Symfony2 Request object and returns a Symfony2 Response object Used by all the classes that act as a Kernel in Symfony2 (ie: HttpKernel\HttpCache)
  • 50.
    Addressing the issuesReentrance Override the super globals Create a fresh new context each time Filter chain Replace sfRenderingFilter by a noRenderingFilter class Create a Symfony2 Response object and returns it
  • 51.
    Final app architectureEsiCacheKernel SymfonyWrapperKernel symfony 1 application
  • 52.
  • 53.
    Then… You haveto design your app to serve HTML fragments!
  • 54.
    Designing your appDon’t think partials or components, think actions! Actions render HTML fragments Actions MUST define explicitly the response cache headers.
  • 55.
  • 56.
  • 57.
    Our choices Thechoice of symfony 1 The choice of Symfony2 The choice to mix Expiration over validation
  • 58.
    This is symfony1: DO NOT TRY ANY OF THIS AT HOME!
  • 59.
    Our results Itworks! The frontend is scalable and extensible Performance is nice, but we needed to improve the Store.php class
  • 60.
    What to donext ?
  • 61.
    Implementing cache validationThe application needs to garantee freshness How to avoid hitting the application ?
  • 62.
    Proxy ESI Newresponse Or 304 URL-> {ETag} ETag-> lastmodified If Etag absent or stale Response with HTTP headers Etag LastModified Client Request with HTTP headers If-None-Match If-Modified-Since App New response Or 304 If cache entry is not fresh enough Cache Validation Optimizer
  • 63.
    Contact @ L’ExpressSébastien Angèle [email_address] Jérôme Macias [email_address]
  • 64.
    Questions ? MarcWeistroff @futurecat [email_address] http://www.marcw.net Emmanuel Cohen @emmanuelcohen [email_address]
  • 65.
    Thank you! Pleaserate this talk at http://joind.in/2749