Microservices: Packs small, plays BIG!
Stephan Hochdörfer // Feb. 6th 2016
About me
Stephan Hochdörfer
Head of Technology , bitExpert AG (Mannheim, Germany)
S.Hochdoerfer@bitExpert.de
@shochdoerfer
#PHP, #DevOps, #Automation
#phpugffm, #phpugmrn, #unKonf
The curse of the monolith
Intimidating "old" codebase
Complex code is hard to understand; overloaded IDE, development slowes down
Increases the likelyhood to make errors
Does not allow us to move fast (agile)
Small change, big impact
Every single small change needs a full rebuild. Takes a long time (Long test cycle, long deployment
phase).
Obstacle for frequent changes and deployments. No continious deployment!
Long-term commitment
Commitment to an "old technology". Hard to bring in the "new stuff".
What about a rewrite?
Changing the tech stack implies a complete rewrite. There`s no partial rewrite. Rewrite will fail.
Netscape 4 Rewrite - Fail (IE won)
Borland dBase - Fail (Access won)
Borland Quattro Pro - Fail (Excel won)
Microsoft always won (because they made no real rewrites - or at least not with the whole team)
The legacy truth
« Legacy code is a business asset that helped
the business get where it is. Treat it with respect. »
- @ylarrivee
Treat it with respect: Keep it and "modernize" it in the best possible way.
The LTS truth
« good long term software is not commonly about reuse,
its about the ability to rewrite completely isolated bits
without hitting the big bang » - @gregyoung
The solution?
« [...] This is the Unix philosophy: Write programs that do one thing and do it well. »
- Doug McIlroy
Doug McIlroy, inventor of the Unix pipe
Programs need to cooperate
« [...] Write programs to work together. Write programs to handle text streams, because that
is a universal interface. » - Doug McIlroy
Doug McIlroy, inventor of the Unix pipe
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
Written 25 March 2014
Amazon, Netflix, Soundcloud, ...
Just SOA? Or better?
« I guess it is easier to use a new name (Microservices)
rather than say that this is what SOA actually meant [...] » - @arnonrgo
Small problem domain
Bounded Context in DDD terms
The same way we do it when structuring classes or methods.
Single Responsibility
« A class should have one, and only one, reason to change. » - Robert C. Martin
We split a "big problem" into smaler parts and solve them independently.
"Isolated process"
Docker
Docker is an open platform for developers and sysadmins to build, ship, and run distributed
applications.
Microservices platform
Alternatives:
https://tsuru.io/
https://flynn.io/
Deployment Automation
Alternatives:
http://deployer.org/
http://rocketeer.autopergamene.eu/
http://kohkimakimoto.github.io/altax/
Built and deployed in isolation
Owns its data storage
MySQL, PostgreSQL, NoSQL database, Filesystem, ...
Own datastore makes it easier to scale.
Simple communication layer
Standardized protocols, e.g HTTP
Smart endpoints, dumb pipes
« Be of the web, not behind the web. » - Ian Robinson
SOA: Dump endpoints and smart pipes
Open/closed principle
« You should be able to extend a classes behavior, without modifying it. » -
Robert C. Martin
Counts for the service logic as well the as data structures used for request and response.
JSON extensibility could be a problem, XML might be a better solution
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" ]
}
Open/closed principle applies also for your datastructures!
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"
}]
}
Open/closed principle applies also for your datastructures! Plan ahead!
You build it, you own it
With microservices, the old IT mindset just doesn't work. Each microservice is different, and unique
skillsets are required to understand, manage, and deploy them. A centralized IT department cannot
possibly cover the wide array of technologies spanning all microservices.
Why Microservices?
« Microservices are organised around business capabilities. » - Martin Fowler
Old: Focus on technolgy (UI team, DBA team)
New: Focus on business capabilities (inventory management, ...)
The OODA loop
OODA: Observe - Orient - Decide - Act
The faster you can get around this loop, the faster you learn something new about your customer and the
market, the more agile and competitive you get. Enterprises that do this often find improvement in
quality of their products and their ability to learn.
Team organization
Fundamental truth: It`s not about code, it`s about working together.
Microservices is much more about about team organization rather than software architecture. Architecture
and team organization is always heavily coupled together.
Small Focused Teams
"Two pizza teams", Jeff Bezos (Amazon)
http://99u.com/articles/7255/the-jeff-bezos-school-of-long-term-thinking
Empower developers
Trusting developers, and promoting a culture of freedom with responsibility reduces software delivery
times and increases success rates.
Pick the right tool for the job
Replace it if it does not work
Replace your service if it does not work
Liskov substitution principle
« Derived classes must be substitutable for their base classes. » - Robert C. Martin
Easy scaling
Microservices are small. Small services are easier to scale than a monolith.
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
Robert A. Heinlein, The Moon Is a Harsh Mistress, 1966
Not easy!
« If you can’t build a monolith, what makes you think
microservices are the answer? » - Simon Brown
Small services win!
« Small teams typically work better than big teams.
Small services typically work better than monoliths.
#microservices #microservice » - @microsvcs
What does "small" mean?
« @olivergierke Micro Services are neither
micro nor service. :-) » - @ewolff
Microservices, Nanoservices - size not matter. Replaceability matters!
Interface Segregation
« Make fine grained interfaces that are client specific. » - Robert C. Martin
Size does not matter, functionality does.
Standardise in between
Standardize deployment, monitoring/logging, interfaces, error handling
Standardise in the gaps between services - be flexible about what happens inside the boxes.
Monitoring and Logging
Microservices monitoring must be instantly responsive, able to detect failure or situations requiring
rollback, in seconds, and must be completely automated, no human intervention required at any time. The
tooling must enable this, provisioning agent-based logging and allowing services to be deployed with all
monitoring hooks and logging facilities prewired and ready to go. As with most things
microservices-related, doing this correctly results in more complexity and overhead in the tooling.
Avoid distributed transactions
Avoid distributed transactions if at all possible.
Avoid cascading failures
Use timeouts, circuit breakers and bulk-heads to avoid cascading failure.
Design for failure
Chaos Monkey - Randomly terminates one of the systems in a group
Janitor Monkey - Clean up AWS instances
Conformity Monkey - Looks for instances that are not conforming to predefined rules for the best
practices.
Design for failure
« @olivergierke No. I meant to says that REST is not the
most difficult problem for Microservices. E.g. resilience
is probably harder. » - @ewolff
Resilience
Port of Nextflix Hystrix to PHP.
Release early, release often!
Don’t let changes build up - release as soon as you can, and preferably one at a time.
Automate all the things!
Automation is the glue that holds everything together.
In a world where microservices come and go, grow and shrink, and migrate around racks and data centers
in seconds - there's absolutely no room for manual intervention. All aspects of deployment, monitoring,
testing, and recovery must be fully automated. For example, monitoring a service should occur instantly
and automatically by virtue of it being deployed, not requiring a separate manual step.
Dependency Inversion
« Depend on abstractions, not on concretions. » - Robert C. Martin
Lookup services to not explicitly communicate with a specific instance!
Service Discovery
Service discovery and configuration made easy. Distributed, highly available and datacenter aware.
Service Discovery (e.g. mysql, web), Key/Value Store for application configuration.
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!
Document your changes!
Treat your API consumers as customers!
Tools: https://apiblueprint.org, http://swagger.io,
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' ]));
}
}
Acts as an abstraction for 3rd party services using search. Does not matter if in the first place a
PostgreSQL database with full-text search capabilities is used or later on elasticsearch. The
"interface" stays the same. Makes things easier to change.
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 ());
Acts as an abstraction for 3rd party services using search. Does not matter if in the first place a
PostgreSQL database with full-text search capabilities is used or later on elasticsearch. The
"interface" stays the same. Makes things easier to change.
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 ());