Transforming legacy PHP applications with Symfony2 and Varnish

49
Transforming legacy applications with Symfony2 and Varnish

description

The careerswales.com platform manages the education and professional progression of millions of people in Wales. When challenged with upgrading its ageing application stack to suit modern standards, we devised a solution with Symfony2 at its core. In this talk I'll discuss how the new stack was implemented, focussing on how we took advantage of Symfony2's first-class support for reverse-proxy Varnish to phase the deployment of the new system and improve performance by a significant amount. I'll also talk about the API we created to bridge its SQL Server / MySQL database platforms, and how Symfony2 was used to provide a single-sign-on solution across all of its web applications.

Transcript of Transforming legacy PHP applications with Symfony2 and Varnish

Page 1: Transforming legacy PHP applications with Symfony2 and Varnish

Transforming legacy applications with Symfony2 and Varnish

Page 2: Transforming legacy PHP applications with Symfony2 and Varnish
Page 3: Transforming legacy PHP applications with Symfony2 and Varnish
Page 4: Transforming legacy PHP applications with Symfony2 and Varnish

JULY 2012

10 CONCURRENT USERS

~20 SECONDS AVERAGE

HOMEPAGE -> LOGIN -> PERSONAL DETAILS

Page 5: Transforming legacy PHP applications with Symfony2 and Varnish

Why so slow?

PHP4

SQL Server and Windows Server

Sub-optimal caching strategy

Page 6: Transforming legacy PHP applications with Symfony2 and Varnish
Page 7: Transforming legacy PHP applications with Symfony2 and Varnish

“Rewriting the code from scratch ... (is) the single worst strategic mistake a software company can make.”

- Joel Spolsky

Page 8: Transforming legacy PHP applications with Symfony2 and Varnish

“... the quick fix is like quicksand: The clarity of code goes down and confusion is harvested in its place.”

- Venkat Subramaniam and Andy Hunt

Page 9: Transforming legacy PHP applications with Symfony2 and Varnish

The Plan

Reduce cost, improve performance

Develop new application framework

Gradual deployment to careerswales.com

API to access shared data

Single sign on and shared sessions

Page 10: Transforming legacy PHP applications with Symfony2 and Varnish

Legacy CMS New Applications

CAREERSWALES.COM

Page 11: Transforming legacy PHP applications with Symfony2 and Varnish

... ENTER SYMFONY2

Page 12: Transforming legacy PHP applications with Symfony2 and Varnish

Why Symfony2?

Used successfully in other projects

Excellent 3rd party libraries

Flexible and easy to extend

Facilitates best practice

Page 13: Transforming legacy PHP applications with Symfony2 and Varnish

PART 1: THE CMS

Page 14: Transforming legacy PHP applications with Symfony2 and Varnish

Catalyst CMS

Cutting edge stack - PHP 5.4, Nginx, FPM

Reusable code through Symfony2 bundles

Inspired by Symfony2 CMF and Sonata

Fraction of the code to maintain

Page 15: Transforming legacy PHP applications with Symfony2 and Varnish
Page 16: Transforming legacy PHP applications with Symfony2 and Varnish

PART 2: THE API

Page 17: Transforming legacy PHP applications with Symfony2 and Varnish

Take it to the bridge

Bridges MSSQL & MySQL databases

Acts as a facade

Linux + MSSQL = PAIN

Caching with Symfony2 and Doctrine

Page 18: Transforming legacy PHP applications with Symfony2 and Varnish

SQL Server

API Application (Symfony2)

Third parties

MySQLWebsite

Application(Symfony2)

Page 19: Transforming legacy PHP applications with Symfony2 and Varnish

PART 3: SINGLE SIGN ON

Page 20: Transforming legacy PHP applications with Symfony2 and Varnish

Single sign on

Single authentication system for all applications

Uses Central Authentication Service (CAS) protocol

BeSimpleSsoAuthBundle does heavy lifting

Custom modifications via DI container

Page 21: Transforming legacy PHP applications with Symfony2 and Varnish

PART 4: VARNISH

Page 22: Transforming legacy PHP applications with Symfony2 and Varnish

Varnish

Frontend proxy or HTTP accelerator

Sits between client and server

Shares cached responses between clients

Can perform load balancing and routing

Page 23: Transforming legacy PHP applications with Symfony2 and Varnish

Without Varnish

Client

Client

Client

HTTP://WWW.CAREERSWALES.COM/EN/

Page 24: Transforming legacy PHP applications with Symfony2 and Varnish

Without Varnish

Client

Client

Client

TTL = 1 DAY

TTL = 1 DAY

TTL = 1 DAY

HTTP://WWW.CAREERSWALES.COM/EN/

Page 25: Transforming legacy PHP applications with Symfony2 and Varnish

With Varnish

Client

Client

Client

Varnish

HTTP://WWW.CAREERSWALES.COM/EN/

Page 26: Transforming legacy PHP applications with Symfony2 and Varnish

With Varnish

Client

Client

Client

Varnish

TTL = 1 DAYTTL = 1 DAY

TTL = 1 DAY

TTL = 1 DAY

HTTP://WWW.CAREERSWALES.COM/EN/

Page 27: Transforming legacy PHP applications with Symfony2 and Varnish

With VarnishClient

Client

Client

Varnish

Client Client Client Client

HTTP://WWW.CAREERSWALES.COM/EN/

Page 28: Transforming legacy PHP applications with Symfony2 and Varnish

With VarnishClient

Client

Client

Varnish

Client Client Client Client

HTTP://WWW.CAREERSWALES.COM/EN/

Page 29: Transforming legacy PHP applications with Symfony2 and Varnish

ESI CachingEdge Side Includes

Identifies blocks of HTML which are dynamic

Blocks are independent of the main response

Blocks can be cached and expired individually

Blocks can be identified as public (cacheable) or private (not cacheable)

Page 30: Transforming legacy PHP applications with Symfony2 and Varnish

TTL = 5 MINS

TTL = 5 DAYS

Page 31: Transforming legacy PHP applications with Symfony2 and Varnish

INVALIDATED

INVALIDATED

INVALIDATED

Page 32: Transforming legacy PHP applications with Symfony2 and Varnish

Carousel Block Caching

Straightforward caching

No personalisation, same for all users

Page 33: Transforming legacy PHP applications with Symfony2 and Varnish

Carousel Block Cachingpublic function indexAction(){ $response = new Response(); // cache for 1 minute $response->setMaxAge(60); $response->setPublic(); return $this->render( 'BoxUK:Default:index.html.twig', array(), $response );}

Page 34: Transforming legacy PHP applications with Symfony2 and Varnish

Login Button Caching

More complex: two different states

Can use varying to store two different caches

Use cookies to provide information to Varnish

BUT don’t want to vary on cookie

Page 35: Transforming legacy PHP applications with Symfony2 and Varnish

Login Button Cachingpublic function indexAction(){ $response = new Response(); // cache for 1 minute $response->setMaxAge(60); $response->setPublic(); $response->setVary('Logged-In'); return $this->render( 'BoxUK:Default:index.html.twig', array(), $response );}

Page 36: Transforming legacy PHP applications with Symfony2 and Varnish

Login Button Cachingpublic function onKernelResponse( FilterResponseEvent $event){ $response = $event->getResponse();

$loggedIn = $this->context->isGranted( 'IS_AUTHENTICATED_FULLY' ) ? 'true' : 'false';

$response ->headers ->set('Logged-In', $loggedIn);}

Page 37: Transforming legacy PHP applications with Symfony2 and Varnish

Login Button Cachingpublic function onKernelResponse( FilterResponseEvent $event){ $response = $event->getResponse();

$cookie = new Cookie('Logged-In',$loggedIn, ...);

$response ->headers ->setCookie($cookie);}

Page 38: Transforming legacy PHP applications with Symfony2 and Varnish

Login Button Caching

if (req.http.Cookie ~ 'Logged-In=true') { set req.http.Logged-In = 'true';}

Varnish cache keys are hashed on URL (host, path, etc) and vary data

Symfony takes care of the way out

On the way in, we have to fake the header to reproduce the hash

Page 39: Transforming legacy PHP applications with Symfony2 and Varnish

Routing

Varnish directs requests to given ‘backends’

Load balancing, e.g. round robin

More complex logic via VCL (Varnish Configuration Language)

No EC2 load balancers!

Page 40: Transforming legacy PHP applications with Symfony2 and Varnish

RoutingOld

applications

New applications

10.1.2.1

10.1.2.2

Client Varnish

Examine request

Page 41: Transforming legacy PHP applications with Symfony2 and Varnish

Defining backendsbackend legacy_applications { .host = "10.1.2.1"; .port = "80";}

backend new_applications { .host = "10.1.2.2"; .port = "80";}

Page 42: Transforming legacy PHP applications with Symfony2 and Varnish

Routing by regexsub vcl_recv {! if (req.url ~ "^(.*)www.careerswales.com/old-request-format") {! set req.backend = legacy_applications;! return(pipe);! }! if (req.url ~ "^(.*)www.careerswales.com/new-request-format") {! set req.backend = new_applications;! return(pipe);! }}

Page 44: Transforming legacy PHP applications with Symfony2 and Varnish

JULY 2012

10 CONCURRENT USERS

~20 SECONDS AVERAGE

HOMEPAGE -> LOGIN -> PERSONAL DETAILS

Page 45: Transforming legacy PHP applications with Symfony2 and Varnish

JULY 2013

10 CONCURRENT USERS

~4 SECONDS AVERAGE

HOMEPAGE -> LOGIN -> PERSONAL DETAILS

Page 46: Transforming legacy PHP applications with Symfony2 and Varnish

Conclusions

Observable speed increase of 560%No loss of functionality or downtime

No loss of functionality or downtime

Substantially less ‘hardware’

More complex environment

Page 47: Transforming legacy PHP applications with Symfony2 and Varnish
Page 48: Transforming legacy PHP applications with Symfony2 and Varnish
Page 49: Transforming legacy PHP applications with Symfony2 and Varnish

Questions?

@craigmarvelley