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

Decoupling your application

Decoupling your application

Symfony Live Paris 2014

Find this presentation at:
http://moquet.net/talks/symfony-live-2014/

Original description:
http://paris2014.live.symfony.com/speakers#session-1131

Matthieu Moquet

April 08, 2014
Tweet

More Decks by Matthieu Moquet

Other Decks in Programming

Transcript

  1. Covoiturage.fr 1 monolithic PHP app o Core website o Web mobile o B2B

    platform o Backoffice tools o Web views (mobile apps) o External widgets
  2. 2.0

  3. Services & Controllers §  Should controllers access the repository? § 

    How should I split my services? §  Is ContainerAware that bad? §  How to organize my Business Layer?
  4. Events §  Listen on Doctrine events? §  Create your own?

    ACTION / PRE_ACTION / POST_ACTION ? §  Subscribers VS. Listeners
  5. With a few developers… At the beginning, you need to

    start quickly, (but you take time to write conventions). Legacy App New App
  6. $ app/console assetic:dump Dumping all dev assets. Debug mode is

    on. 23:00:32 [file+] /path/to/web/css/0e781b6.css 23:00:35 [file+] /path/to/web/css/0e781b6_part_1_bootstrap_1.css 23:00:35 [file+] /path/to/web/css/0e781b6_part_2_buttons_1.css 23:00:35 [file+] /path/to/web/css/0e781b6_part_2_card_2.css 23:00:35 [file+] /path/to/web/css/0e781b6_part_2_form_3.css 23:00:35 [file+] /path/to/web/css/0e781b6_part_2_grid_4.css 23:00:36 [file+] /path/to/web/css/0e781b6_part_2_list_5.css 23:00:36 [file+] /path/to/web/css/0e781b6_part_2_navbar_6.css 23:00:36 [file+] /path/to/web/css/0e781b6_part_2_panel_7.css 23:00:37 [file+] /path/to/web/css/0e781b6_part_2_vcard_9.css 23:00:37 [file+] /path/to/web/js/e66598b.js 23:00:37 [file+] /path/to/web/js/e66598b_jquery_1.js 23:00:37 [file+] /path/to/web/js/e66598b_bootstrap_2.js 23:00:37 [file+] /path/to/web/js/e66598b_script_3.js
  7. $ phpunit -c app ........................... .............. (63/975) .......................... ............... (126/975)

    .............. ........................... (189/975) .......F................ ................. (252/975) .............F....
  8. What if we want to change The backend framework? We

    don’t plan to change it, and we couldn’t
  9. What if we want to change The testing framework? We

    won’t rewrite the whole test suite. But we can use several frameworks at the same time (eg. Behat)
  10. What if we want to change The frontend framework? Well,

    we are stuck with Bootstrap2. Updating to Bootstrap3 or rewriting our own will take time.
  11. What if we want to change The assets builder? Assetic

    took too long to compile all assets. We moved to asset management with Grunt.
  12. What if we want to change The data layer? Actually

    frontend servers make MySQL queries. But in the long term, it’s not a good practice (see coming slides).
  13. Think as small as possible Microservices The secret to building

    large apps is never build large apps. Break your application into small pieces. Then, assemble those testable, bite-sized pieces into your big application — Justin Meyer
  14. Request-Response Id   Firstname   Lastname   Pseudo   Email

      Birthday   1337   Ma'hieu   Moquet   Ma'Ketmo   ma'[email protected]   1988-­‐12-­‐17  
  15. Request-Response However front-end servers should NOT access the database directly

    It should fetch normalized data from an internal service API for the win!
  16. Request-Response Even RabbitMQ can be used for synchronous requests scrutinizer-ci/rabbitmq

    src/Scrutinizer/RabbitMQ/Rpc http://www.rabbitmq.com/tutorials/tutorial-six-python.html
  17. Command Perfect for asynchronous jobs §  Send e-mails / SMS

    / PUSH notifications §  Image processing §  Data indexation §  Saving complex data §  etc.
  18. Command Service is accessible via a queueing system only (not

    REST) §  RabbitMQ §  ActiveMQ §  Beanstalkd §  Gearman §  … More at http://queues.io
  19. Sending Newsletters publish 100k messages Create an army of workers

    in AWS consume send mails message payload = emails address + content App Scheduler (Java + Quartz) Worker NL @10am segment X Get users of segment X (Scroll ElasticSearch)
  20. PubSub $dispatcher = new EventDispatcher();! ! // Listen using an

    object or a callback! $listener = new AcmeListener();! $dispatcher->addListener('foobar', array($listener, 'onFoobar'));! ! $dispatcher->addListener('foobar', function (Event $event) {! // do something else with the events! });! ! // Dispatch event! $dispatcher->dispatch('foobar', $event);! Example with the Symfony EventDispatcher
  21. PubSub Notify your infrastructure of every business events Publish events

    without knowing who is listening Create services without any core changes
  22. Now we have the keys to start a distributed architecture

    let’s start decoupling our application… Front-end desktop + mobile Hard to split in several projects (need to delegate jobs) API For mobile apps & partners Backoffice Set of administration tools Workers Already decoupled from the core app
  23. Backoffice — CRUD Some tools are just data manipulation: – User

    Management – Blog – FAQ GET /users PUT /users/123 Data Layer
  24. Backoffice — Moderation Manage user « data » which need

    to be moderated user.upload_avatar user.edit_bio user.left_rating UI to check data manually Auto detect spam & non compliant data Machine Learning data.received data.treated send mails
  25. « OAuth is an open standard for authorization […] to

    access server resources on behalf of a resource owner » — Wikipedia
  26. OAuth2 Grant Types Authorization Code Connect-like workflow Implicit Grant (Direct

    Token) Usefull for JS app Password flow Trusted app (client credentials) Client Credentials Basic (use of client id + secret)
  27. From LDAP to OAuth Given I am on the login

    page Then I should login with my LDAP credentials App LDAP Login
  28. FR3DLdapBundle/config.yml # LDAP Configuration! fr3d_ldap:! driver:! host: "%ldap_host%"! username: "%ldap_username%"!

    password: "%ldap_password%"! baseDn: "%ldap_username%"! user:! baseDn: "%ldap_user_dn%"! filter: "%ldap_user_filter%"! attributes:! - { ldap_attr: "uid", user_method: "setUsername" }! - { ldap_attr: "cn", user_method: "setName" }! - { ldap_attr: "mail", user_method: "setEmail" }! service:! user_manager: "acme.user_manager"!
  29. From LDAP to OAuth Given I am on "/me" with

    "user" access token Then I should get "user" resources in JSON App LDAP OAuth2 API
  30. # HWI OAuth Configuration! hwi_oauth:! firewall_name: "main"! resource_owners:! acme_sso:! type:

    "oauth2"! client_id: "%client_id%"! client_secret: "%client_secret%"! access_token_url: "%base_url%/oauth/v2/token"! authorization_url: "%base_url%/oauth/v2/auth"! infos_url: "%base_url%/api/me”! paths:! identifier: "id"! nickname: "username"! realname: "name"! email: "email"!
  31. id_token Multiple Response Type Encoding Practices. Provides an assertion of

    the identity of the Resource Owner. http://openid.bitbucket.org/oauth-v2-multiple-response-types-1_0.html
  32. However if OAuth is not designed to be an SSO

    protocol, what should I use?
  33. SAML (Security Assertion Markup Language) SAML is an XML-based protocol

    that uses security tokens containing assertions to pass information about a principal between an identity provider, and a consumer. There are bundles/lib for that (but not maintained, see impl.) §  pdias/FOSSamlBundle §  aerialship/SamlSPBundle §  chtitux/sfSAMLPlugin (symfony1)
  34. JWT (JSON Web Token) Payload signed server-side with a JSON

    Web Signature (JWS). auth.   signed token request
  35. firebase/php-jwt curl –H "Authorization: Bearer eyJ0eXAiOiJKV..." example.org $key = "s3cr3t_key";

    $token = array( "sub" => "mattketmo", "aud" => "http://example.com", "exp" => 1356999524, ); $jwt = JWT::encode($token, $key);  // eyJ0eXAiOiJKV...
  36. namshi/jose OpenSSL + cookies // Auth (SSO) $privateKey = openssl_pkey_get_private("file://private.key");

    $jws = new JWS('RS256'); $jws->setPayload([$userId]); $jws->sign($privateKey) setcookie('identity', $jws->getTokenString()); // Client App $jws = JWS::load($_COOKIE['identity']); $publicKey = openssl_pkey_get_public("/public.key"); if ($jws->isValid($publicKey)) { $payload = $jws->getPayload(); $userId = $payload['id']; }
  37. Hawk Shared secret between client & server by Eran Hammer

    Read more at http://alexbilbie.com/2012/11/hawk-a-new-http-authentication-scheme/
  38. Enforce reusable components { "require": { "blablacar/monolog": "~1.0", "blablacar/scheduler-client": "~1.1",

    "blablacar/redis-client": "~1.2", "blablacar/rabbit-mq-admin-toolkit": "dev-master" } }
  39. Be ready for production Don’t loose time in configuration setup

    Parameters for $ENV Config template for $PROJECT Config file for $PROJECT/$ENV Centralized build tool to generate a project configuration file for any environment (local / dev / staging / prod)