Microservices: Klein, aber oho!
Stephan Hochdörfer // 22.04.2015
Über mich
Stephan Hochdörfer
Head of Technology , bitExpert AG Mannheim
S.Hochdoerfer@bitExpert.de
@shochdoerfer
#DevOps, #Automation, #unKonf
Der Fluch des Monolithen
Einschüchternde Codebasis
Komplexer Code der schwer zu verstehen ist, überladene IDE, viele Klassen, viele Methoden
Entwicklung langsam, erhöht die Wahrscheinlichkeit Fehler zu machen (Natur der Sache)
Verhindert dass wir schnell vorhan kommen (Agilität leidet)
Fragiles System
Jede noch so keine Änderung sorgt für einen kompletten Rebuild. Dauert lange (langer Test-Zyklus, Integrationstests, Deployment)
Hintert uns daran oft Änderungen zu machen und zu deployen! Continious Deployment nicht wirklich machbar!
Langfristige Verpflichtung
Wir sind an "alte" Technologien gebunden die vor 10 Jahren "aktuell" waren. Schwer neues zu integrieren.
Versuch eines Rewrites?
Den Tech-Stack auszutauschen heißt ein komplettes Rewrite versuchen. Es gibt kein partielles Rewrite und das Rewrite wird mit ziemlich großer Wahrscheinlichkeit nach hinten los gehen.
Netscape 4 Rewrite - Misslungen (IE hat gewonnen)
Borland dBase - Misslungen (Access hat gewonnen)
Borland Quattro Pro - Misslungen (Excel hat gewonnen)
Die Legacy Wahrheit
Behandle den Legacy Code / den Monolithen mit Respekt: behalte ihn und "modernisiere" ihn langsam nach und nach.
Die Lösung?
« [...] This is the Unix philosophy: Write programs that do one thing and do it well. » - Doug McIlroy
Doug McIlroy, inventor of the Unix pipe
Zusammenarbeit
« [...] 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
Was sind 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
Blogpost geschrieben im März 2014
Unternehmen die verstärkt auf Microservices setzen: Amazon, Netflix, Soundcloud, ...
Kleine Problemdomäne
Bounded Context in DDD Sprache
Gleiches Vorgehen dass wir verwenden um Klassen und Methoden zu strukturieren.
Single Responsibility
« A class should have one, and only one, reason to change. » - Robert C. Martin
"Großes Problem" aufsplitten in kleinere Stücke und diese unabhängig davon lösen.
Isolierter Prozeß
Nicht ein Applikation-Server auf dem alles läuft, sondern ein Applikation-Server für eine Applikation.
Docker
Docker is an open platform for developers and sysadmins to build, ship, and run distributed applications.
Microservices Platform
Alternativen:
https://tsuru.io/
https://flynn.io/
Deployment Automatisierung
Build + Deployment isolieren
Sicherstellen dass es beim Bau und Deployment nicht zu Seiteneffekten kommt.
Idealerweise wenige dependencies, idealerweise keine Dependencies unter den Services
Separater Datenspeicher
MySQL, PostgreSQL, NoSQL Datenbank, Dateisystem, ...
Separater Datenspeicher macht das spätere Skalieren viel einfacher.
Einfache Kommunikation
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
Gilt nicht nur für die Logik in den Services, genau so auch für die Datenstrukturen die ausgetauscht werden
Datenstruktur-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 gilt auch für Datenstrukturen
Datenstruktur-Evolution
{
"id" : 123 ,
"name" : "My Product" ,
"categories" : [{
"id" : 12 ,
"name" : "My category"
}],
"prices" : [{
"price" : 12.34 ,
"currency" : "EUR"
}, {
"price" : 14.26 ,
"currency" : "USD"
}]
}
Vorrausschauend planen / arbeiten. Ähnlich wie bei REST Schnittstellen, ggf. mit Versionierung arbeiten, kann aber Wartung verkomplizieren!
Bauen, Deployen, Supporten
You build it, you run it!
Keine Trennung zwischen Entwickung und Operations - DevOps. Jeder Micoservice ist anders, benutzt andere Technologien. Eine zentrale IT Abteilung kann das nicht mehr leisten, auch nicht das permante Deployment von Entwicklungen durch mehrere Teams.
Warum Microservices?
« Microservices are organised around business capabilities. » - Martin Fowler
Alt: Technologische Trennung bei den Teams (UI team, DBA team)
Neu: Fokus auf Business Prozesse
Observe, Orient, Decide, Act
OODA: Observe - Orient - Decide - Act
Macht jedes Unternehmen, direkt oder indirekt. Je schneller man den Zyklus durchlaufen kann desto größer ist der Vorteil gegenüber Mitbwerbern. Man lernt schneller was Kunden wollen, wie der Markt aussieht und ist dadurch entsprechend stärker im Wettbewerb aufgestellt. Unternehmen die den Zyklus durchlaufen verbesseren die Qualität der Software.
Team Organisation
Fundamentale Wahrheit: Es geht hier nicht um Code, es geht um die Optimierung der Zusammenarbeit.
SW-Architektur und Team Organisation hängen stark zusammen - Conways Law
Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization's communication structure
Kleine, fokussierte Teams
"Two pizza teams", Jeff Bezos (Amazon)
Mehr Macht den Entwicklern!
Vertraue deinen Entwicklern. Entwickle eine Kultur von Freiheit und Verantwortung, dies wird die Software verbessern, Deployment-Zeiten minimieren und die Erfolgsrate erhöhen.
Nutze das "passende" Tool...
Backend: Austausch einfacher, da nach "außen" ja nur HTTP Requests / Responses eine Rolle spielen
Frontend: Ggf. schwieriger wenn Frontend-Framework fixe HTML Strukturen vorsieht (bsp. Sencha)
...oder tausche es aus!
Ersetze Tools / Frameworks die nicht so funktionieren wie sie sollen.
Liskov substitution principle
« Derived classes must be substitutable for their base classes. » - Robert C. Martin
Skalierung wird einfacher!
Microservices sind klein, kleine Services sind einfacher zu skalieren als ein großer Monolith.
Einzelne Services können unabhängig von einander skaliert werden!
Entwicklung wird schneller...
...je nach Bedarf!
A/B Testing für Services
Herausforderungen
« There ain’t no such thing as a free lunch. » - Robert A. Heinlein
Robert A. Heinlein, The Moon Is a Harsh Mistress, 1966
Was heißt denn "klein"?
Microservices, Nanoservices - Größe spielt keine Rolle!
Interface Segregation
« Make fine grained interfaces that are client specific. » - Robert C. Martin
Größe spielt keine Rolle, Funktionalität ist wichtig!
Standardisierung notwendig!
Entwickler haben die Freiheit zu entscheiden wie Services gebaut werden, welche Frameworks, Tools, Datastores verwendet werden.
Alles andere muss standardistert werden: Deployment, Monitoring/Logging, Fehlerbehandlungen, Errorcodes
Monitoring und Logging
Monitoring und Logging ist wichtiger denn je. Es muss direkt sichtbar sein wenn ein Miroservice ein Problem verursacht und ich muss nachverfolgen können woher das Problem stammt (Microservice-übergreifend Logfiles analysieren können!). Wie vieles im Kontext von Microservices ist das nicht einfach und resultiert in einem komplexeren Setup was die eigene Infrastruktur und das Tooling angeht!
Keine verteilte Transaktionen!
Verteilte Transaktionen verhindern!
Keine kaskadierende Fehler!
Intensiv mit Timeouts und circuit breakers arbeiten um kaskadierende Fehler vermeiden.
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.
Früh und oft releasen!
Don’t let changes build up - release as soon as you can, and preferably one at a time.
Automatisierung FTW!
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 explictily 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 Beispiel
<dependencies>
<dependency>
<groupId> com.orbitz.consul</groupId>
<artifactId> consul-client</artifactId>
<version> 0.8.2 </version>
</dependency>
</dependencies>
Consul consul = Consul. newClient ();
HealthClient healthClient = consul. healthClient ();
List< ServiceHealth> nodes = healthClient. getHealthyNodes ( "DataService" ). getResponse ();
Dokumentation FTW!
Änderungen dokumentieren!
API Konsumenten wie Kunden behandeln!
Tools: https://apiblueprint.org, http://swagger.io,
jhipster
jhipster Beispiel
$ npm install - g generator- jhipster
$ yo jhipster
$ mvn spring- boot: run
$ yo jhipster: cloudfoundry
Spring Boot
Spring Boot Beispiel
@Controller
class MyApp {
@RequestMapping ( "/" )
@ResponseBody
String home () {
"Hello World!"
}
}
$ spring run app.groovy