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

AutoScaling Symfony Applications

AutoScaling Symfony Applications

One of the biggest value propositions of the cloud was that we would be able to dynamically adapt our infrastructure according to our needs. But it’s not the magic that most people desire and it’s sometimes hard to navigate in a wide range of problems and solutions, which scare a lot of developers away. But if planned right, it’s not that hard too. This session provides an overview of the problems that arise when you want to develop an automatically scalable php application and how to solve them using open-source tools and cloud services.

Luís Faceira

March 08, 2014
Tweet

Other Decks in Programming

Transcript

  1.  Store files on S3 (20 minutes)  Move your

    database to a separate server (10 minutes)  Create AMI image of your server’s disk (15 minutes)  Create an ELB with sticky sessions for that AMI (5 minutes)  Configure CloudWatch to trigger scaling (10 minutes) Good luck!
  2. CEO of be.ubi I’ve been programming and starting ventures since

    I was 12 years old [email protected] Send CV to: [email protected] "u bi qui tous" (adj.): existing or being everywhere at the same time; omnipresent ubi.banking is a modular banking processes management solution used in 8 Portuguese financial institutions. Symfony 1.4 SWE is a patent-pending retail solution that analyzes the Facebook profile of customers in real- time and presents individualized prices. Symfony 2
  3.  The failed promise of the cloud  PaaS vs.

    IaaS  Growing your infrastructure as your userbase grows
  4.  Autoscaling requires changes to the application  Over-engineering for

    the perfect architecture  The fear of vendor lock-in  Premature optimization is the root of all evil!
  5. PaaS  Simpler  API, Deployment and Architectural lock-in 

    Costly  Rigid  CLI? Good for stable applications managed by business IaaS  Quite complex  Deployment lock-in  Cheapest  Flexible and emulatable Good for mutant applications managed by devops
  6. Process:  Disable app  Backup data  Start new

    bigger server  Restore app and data  Redirect  It’s sloooow, involves downtime  But requires no changes to the app  You MUST test the process  Setup monitoring and notifications  You can autoscale vertically but it isn’t worth the effort Vertical
  7. AUTOMATE  Server Provisioning  App Deployment  Backup/Restore 

    Make all envs equal with virtualization  Use Vagrant! Do not not use it!  Infrastructure management code is still code, it should be tested as well! Preparations
  8. OPTIMIZE PERFORMANCE  Lots of great presentations out there! 

    Understand your app’s performance  Focus on the bottleneck  It probably is the database reads  Use a Content-Delivery-Network  Only move forward if you don’t have a clear “next target” Preparations
  9. DECOUPLE SERVICES  Common Web App Architecture:  Web Server

     Database  Cache  Backend  Demand doesn’t oscillate equally across different services, so capacity shouldn’t either  Ensure that all service references to “localhost” are changeable parameters  You can and you should emulate the multiple servers inside vagrant Preparations
  10. # example of decoupling services # parameters.yml default: database_host: localhost

    database_port: ~ cache_service_host: mycache.myapp.com cache_service_port: ~ service_a_host: localhost service_a_port: 123456 service_b_host: serviceb.myapp.com service_b_port: ~ service_c_host: etc.
  11. ISOLATE DATA PERSISTANCE  Persistent storage is the hardest thing

    to scale, so isolate it to leave it to the last  Save the session in the database  Encapsulate file storage in wrapper that can handle:  Network File System  Cloud Storage Provider (e.g. S3)  Use Gaufrette and KnpGaufretteBundle  You can and you should emulate the multiple servers inside vagrant Preparations
  12. # example of storing session in database # app/config/config.yml framework:

    session: # ... handler_id: session.handler.pdo parameters: pdo.db_options: db_table: session db_id_col: session_id db_data_col: session_value db_time_col: session_time services: pdo: class: PDO arguments: - "mysql:host=%database_host%; port=%database_port%; dbname=%database_name%“ - "%database_user%“ - "%database_password%" calls: - [setAttribute, [3, 2]] session.handler.pdo: class: Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler arguments: ["@pdo", "%pdo.db_options%"]
  13. # example of configuring KnpGaufrette to abstract file storage #

    app/config/config.yml knp_gaufrette: adapters: uploads: local: directory: /path/to/my/filesystem create: true uploads_s3: amazon_s3: amazon_s3_id: amazonS3 bucket_name: foo_bucket options: directory: foo_directory # usage when local : gaufrette://uploads/... # usage when cloud : gaufrette://uploads_s3/...
  14. HORIZONTAL SCALING  The architecture and the app must be

    well prepared  Zero downtime  Distribute load across multiple servers:  Load-balancers / Proxys  Round-robin DNS  Process:  Start server  Provision server  Reconfigure load-balancer  You can, and probably should, mix with vertical scaling Computing
  15. EXAMPLE ON AWS  Create a machine image through your

    automated provisioning  Automate the machine image packaging with Packer.io  Generate an AMI on AWS  Create a load-balancer that redirects to machines with that image  In AWS start an AutoScaling group for your AMI  If you want, you can use HAProxy out of the cloud  Setup triggers that create or destroy servers  CloudWatch on AWS  Or an infrastructure controller  Crons on a separate unique server  Proactive AutoScaling Computing
  16. APPROACH A: PARTITIONING  The simplest solution on SQL 

    Separate different subdomains in different databases  Each set of database servers grows on its own  Requires changes to your application  Almost impossible to automate  It just delays the need for horizontal scaling for a while Data
  17. APPROACH B: READ SYNC  Arguable the best solution in

    SQL  All writes are done on one authoritative master server that scales vertically  Data is replicated across multiple slave servers  There may be slight delays  You can hardcode multiple read-replicas on your Doctrine configuration  You can optionally use HAProxy to distribute sql read connections as well  This approach should allow you to support 10s to 100s of thousands users  PS – Write sync does not provide you with extra capacity Data
  18. # Doctrine’s config file # Uses built-in # \Doctrine\DBAL\Connections\MasterSlaveConnection doctrine:

    dbal: driver: %database_driver% host: %database_host% port: %database_port% dbname: %database_name% user: %database_user% password: %database_password% slaves: slave1: host: %database_host_slave1% port: %database_port_slave1% dbname: %database_name_slave1% user: %database_user_slave1% password: %database_password_slave1% slave2: …
  19. APPROACH C: SHARDING  This is the solution usually applied

    by NoSQL, MySQL Cluster, etc.  The writes and reads occur on a different server depending on the has of the row  This is the most scalable solution, scales both writes and reads  Transactions have an higher-toll and are not always supported  It’s not easy to automate resharding, but it’s possible  Leave it to the experts, use provided clustering solutions Data