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

"Liebling, ich habe das Framework geschrumpft!"...

"Liebling, ich habe das Framework geschrumpft!" @ code.talks 2015

Microservices sind zur Zeit in aller Munde. Kein Wunder, denn richtig eingesetzt können sie die Basis für eine hochmodulare und skalierbare Applikation bilden. Doch eine ihrer wesentlichen Eigenschaften wird bei der Wahl eines Frameworks zur Implementierung häufig nicht berücksichtigt: die Reduzierung auf das Wesentliche. Dieser Talk zeigt am Beispiel einer RESTful API eines Microservices, warum weniger Framework zu mehr Performance und besserer Wartbarkeit führen kann, ohne dabei den Entwicklungsaufwand zu erhöhen.

Sebastian Heuer

September 30, 2015
Tweet

More Decks by Sebastian Heuer

Other Decks in Technology

Transcript

  1. Creating a new laravel application $ laravel new myProject
 (…)

    Application ready! Build something amazing.
  2. /app/Http/Controllers/IndexController.php <?php namespace App\Http\Controllers; class IndexController extends Controller { public

    function index() { $result = ['message' => 'Hello World!']; return response(json_encode($result, JSON_PRETTY_PRINT)); } }
  3. /app/Http/Kernel.php <?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel

    extends HttpKernel { /** * The application's global HTTP middleware stack. * * @var array */ protected $middleware = [ \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class, \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, ];
  4. /app/Http/Kernel.php <?php namespace App\Http; use Illuminate\Foundation\Http\Kernel as HttpKernel; class Kernel

    extends HttpKernel { /** * The application's global HTTP middleware stack. * * @var array */ protected $middleware = [ ];
  5. It runs! $ php -S localhost:3000 server.php PHP 5.6.2 Development

    Server started at Wed Sep 30 08:35:01 2015 Listening on http://localhost:3000 Document root is /Users/ $ curl http://localhost:3000 { "message": "Hello World!" }
  6. $ phploc . phploc 2.1.4 by Sebastian Bergmann.
 (…) Size

    Lines of Code (LOC) 529103 Comment Lines of Code (CLOC) 146493 (27.69%) Non-Comment Lines of Code (NCLOC) 382610 (72.31%) Logical Lines of Code (LLOC) 98404 (18.60%) Logical Lines Of Code
  7. Requests per Second $ ab -n 100 http://localhost:3000/ This is

    ApacheBench, Version 2.3 <$Revision: 1663405 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient).....done Concurrency Level: 1 Time taken for tests: 4.811 seconds Requests per second: 20.78 [#/sec] (mean) Time per request: 48.114 [ms] (mean)
  8. Request 1/2 <?php namespace Acme\Rest; class HttpRequest implements HttpRequestInterface {

    /** * @var array */ private $server = []; /** * @param array $server */ public function __construct(array $server) { $this->server = $server; }
  9. Request 2/2 /** * @return string */ public function getPath()

    { return parse_url($this->server['REQUEST_URI'], PHP_URL_PATH); } /** * @return string */ public function getMethod() { return mb_strtolower($this->server['REQUEST_METHOD']); } }
  10. Response 1/2 <?php class JsonResponse implements ResponseInterface { /** @var

    array */ private $body = []; /** @var int */ private $statusCode = 200; /** * @param array $body * @param int $statusCode */ public function __construct($statusCode, array $body) { $this->statusCode = $statusCode; $this->body = $body; }
  11. Response 2/2 /** * @return string */ public function flush()

    { http_response_code($this->statusCode); echo json_encode($this->body, JSON_PRETTY_PRINT); } }
  12. RequestHandler <?php namespace Acme\Rest; class IndexRequestHandler implements RequestHandlerInterface { /**

    * @param HttpRequestInterface $request * @returns JsonResponse */ public function handle(HttpRequestInterface $request) { return new JsonResponse(200, ['message' => 'Hello World']); } }
  13. Route 1/3 class Route { /** @var string */ private

    $method = 'get'; /** @var string */ private $path = ''; /** @var RequestHandlerInterface */ private $requestHandler;
  14. Route 2/3 /** * @param string $method * @param string

    $path * @param RequestHandlerInterface $handler */ public function __construct($method, $path, RequestHandlerInterface $handler) { $this->method = $method; $this->path = $path; $this->requestHandler = $handler; } /** * @return RequestHandlerInterface */ public function getRequestHandler() { return $this->requestHandler; }
  15. Route 3/3 /** * @param HttpRequestInterface $request * * @return

    bool */ public function matches(HttpRequestInterface $request) { return $this->method == $request->getMethod() && 
 $request->getPath() == $this->path; } }
  16. Router 1/2 <?php namespace Acme\Rest; class Router { /** *

    @var Route[] */ private $routes = []; /** * @param Route $route */ public function addRoute(Route $route) { $this->routes[] = $route; }
  17. Router 2/2 /** * @param HttpRequestInterface $request * * @return

    ResponseInterface * @throws RoutingException */ public function route(HttpRequestInterface $request) { foreach ($this->routes as $route) { if (!$route->matches($request)) { continue; } return $route->getRequestHandler(); } throw new RoutingException( sprintf('No route for %s %s', $request->getMethod(), $request->getPath()) ); }
  18. Application 1/2 <?php namespace Acme\Rest; class Application { /** *

    @var Router */ private $router; /** * @param Router $router */ public function __construct(Router $router) { $this->router = $router; }
  19. Application 2/2 /** * @param HttpRequestInterface $request * * @return

    JsonResponse */ public function run(HttpRequestInterface $request) { $requestHandler = $this->router->route($request); $response = $requestHandler->handle($request); return $response; } }
  20. Tying everything together <?php namespace Acme\Rest; require __DIR__ . '/../src/autoload.php';

    $router = new Router(); $application = new Application($router); $router->addRoute( new Route('get', '/', new IndexRequestHandler()) ); $response = $application->run(new HttpRequest($_SERVER)); $response->flush();
  21. It runs too! $ php -S localhost:3000 example/application.php PHP 5.6.2

    Development Server started at Wed Sep 30 09:20:04 2015 Listening on http://localhost:3000 Document root is /Users/sebastian/projects/php/restframework Press Ctrl-C to quit. $ curl http://localhost:3000 { "message": "Hello World" }
  22. $ phploc . phploc 2.1.4 by Sebastian Bergmann. (…) Size

    Lines of Code (LOC) 338 Comment Lines of Code (CLOC) 109 (32.25%) Non-Comment Lines of Code (NCLOC) 229 (67.75%) Logical Lines of Code (LLOC) 66 (19.53%) Logical Lines Of Code
  23. $ ab -n 100 http://localhost:3000/ This is ApacheBench, Version 2.3

    <$Revision: 1663405 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking localhost (be patient).....done Concurrency Level: 1 Time taken for tests: 0.101 seconds Requests per second: 992.59 [#/sec] (mean) Time per request: 1.007 [ms] (mean) Requests per Second