Microservices:
Packs small, plays BIG!

Stephan Hochdörfer // October 21 2015

About me


  • Stephan Hochdörfer
  • Head of Technology, bitExpert AG
    (Mannheim, Germany)
  • S.Hochdoerfer@bitExpert.de
  • @shochdoerfer

  • #PHP, #DevOps, #Automation

The curse of the monolith

Intimidating "old" codebase

Small change, big impact

Long-term commitment

What about a rewrite?

The legacy truth



The LTS truth



The solution?




« [...] This is the Unix philosophy: Write
programs that do one thing and do it well. »
- Doug McIlroy

Programs need to cooperate




« [...] Write programs to work together. Write programs to
handle text streams, because that is a universal interface. »
- Doug McIlroy

What are Microservices?




« [...] approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms. »
- James Lewis, Martin Fowler

Just SOA? Or better?



Small problem domain

Single Responsibility




« A class should have one, and
only one, reason to change. »
- Robert C. Martin

"Isolated process"

Docker



Microservices platform

Deployment Automation

Built and deployed in isolation

Owns its data storage

Simple communication layer

Smart endpoints, dumb pipes




« Be of the web, not behind the web. »
- Ian Robinson

Open/closed principle




« You should be able to extend a classes
behavior, without modifying it. »
- Robert C. Martin

Data structures evolution

{
  "id": 123,
  "name": "My Product",
  "categories": [{
    "id": 12,
    "name": "My category"
  }],
  "price": 12.34
  "currency": "EUR"
}
{
  "id": 123,
  "name": "My Product",
  "categories": [{
    "id": 12,
    "name": "My category"
  }],
  "price": [12.34, 14.26]
  "currency": ["EUR", "USD"]
}

Data structures evolution

{
  "id": 123,
  "name": "My Product",
  "categories": [{
    "id": 12,
    "name": "My category"
  }],
  "prices": [{
    "price": 12.34,
    "currency": "EUR"
  }, {
    "price": 14.26,
    "currency": "USD"
  }]
}

You build it, you own it

Why Microservices?




« Microservices are organised around
business capabilities. » - Martin Fowler

The OODA loop

Team organization

Small Focused Teams

Empower developers

Pick the right tool for the job

Replace it if it does not work

Liskov substitution principle




« Derived classes must be substitutable
for their base classes. » - Robert C. Martin

Easy scaling

Increase development speed

...but choose a healthy pace!

Try out new ideas...

Segmented feature toggles

Microservices Challenges




« There ain’t no such thing as a free lunch. »
- Robert A. Heinlein

Not so easy!



Small services win!



What does "small" mean?



Interface Segregation




« Make fine grained interfaces that
are client specific. » - Robert C. Martin

Standardise in between

Monitoring and Logging

Avoid distributed transactions

Avoid cascading failures

Design for failure

Design for failure



Resilience

Release early, release often!

Automate all the things!

Dependency Inversion




« Depend on abstractions, not on concretions. »
- Robert C. Martin

Service Discovery


Service Discovery Example

$> composer.phar require sensiolabs/consul-php-sdk
<?php
require_once __DIR__.'/vendor/autoload.php';

$sf = new SensioLabs\Consul\ServiceFactory();
$kv = $sf->get('kv');

$kv->put('test/foo/bar', 'bazinga');
$kv->get('test/foo/bar', ['raw' => true]);
$kv->delete('test/foo/bar');

Document your APIs!

Microservice Example

Microservice Example

$> composer.phar require zendframework/zend-diactoros
$> composer.phar require zendframework/zend-stratigility
use Zend\Stratigility\MiddlewarePipe;
use Zend\Stratigility\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Zend\Diactoros\Response\JsonResponse;

class SearchMiddleware implements MiddlewareInterface
{
    public function __invoke(Request $request, Response $response,
        callable $next = null)
    {
        $params = $request->getQueryParams();
        $service = new SearchService();
        return new JsonResponse($service->search($params['search']));
    }
}

Microservice Example

use Zend\Stratigility\MiddlewarePipe;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;

$api = new MiddlewarePipe();
$api->pipe(new SearchMiddleware());
$response = $api(ServerRequestFactory::fromGlobals(), new Response());

Extending your Microservice

$> composer.phar require oscarotero/psr7-middlewares
use Zend\Stratigility\MiddlewarePipe;
use Zend\Diactoros\ServerRequestFactory;
use Zend\Diactoros\Response;
use Psr7Middlewares\Middleware\Firewall;

$api = new MiddlewarePipe();
$api->pipe(new Firewall(['127.0.0.1']));
$api->pipe(new SearchMiddleware());
$response = $api(ServerRequestFactory::fromGlobals(), new Response());







Thank you! Questions?







Do not forget to rate the talk:
https://joind.in/15572