Bij de Politie is veel aandacht voor het verbeteren van de ICT-omgeving, zowel bij het bouwen van de nieuwe organisatie (van 26 korpsen naar één politie), als in het ondersteunen van de operatie. Een goed voorbeeld is het project waar wij aan werken. Dit is een onderzoeksomgeving, waarmee eindgebruikers digitale informatie op een veilige, forensische, geborgde manier kunnen gebruiken. Een onderdeel van deze omgeving is een applicatie waar een eindgebruiker digitaal materiaal verzamelt ten behoeve van opsporing en onderzoek.
Deze applicatie is begonnen als elk ander Java web-project met haar typische opbouw. Deze opbouw bevatte de traditionele presentatie, business en datalaag. Naarmate het project groeide werd steeds duidelijker dat deze opbouw niet voldeed.
Dit had enerzijds te maken met de toenemende complexiteit en integratie van de functionele wensen, alsmede dat het applicatielandschap een state-of-the-art Openstack private cloud omgeving is met haar specifieke wensen. Daarnaast merkte we als team, dat er steeds meer verwevenheid ontstond in onze code. Het werd tijd voor een wat onconventioneler aanpak: een kleine revolutie binnen de organisatie.
Opsplitsen naar functionaliteit
We zijn begonnen met het herschikken van de verschillende functionaliteit. Hiervoor hebben we losjes de principes van Domain Driven Design gehanteerd. Dit houdt in dat elk specifiek onderdeel van de totale applicatie een eigen (sub)domein heeft.
De raakvlakken met andere domeinen worden ontsloten met een REST interface voor point-to-point communicatie en Kafka voor pub-sub communicatie. We hebben gekozen voor REST en Kafka, omdat dit makkelijk horizontaal schaalt in een cloudomgeving.
Versiebeheer
Het beheren van versies is door de splitsing naar meerdere applicaties heel belangrijk. Versiebeheer is en blijft een uitdaging, ondanks de verscheidenheid aan tooling, zoals Maven. De keuze voor microservices kan zelfs zorgen voor een grotere uitdaging. Immers moet je nu voor elke microservice de verschillende versies tussen services en de third-party dependencies bijhouden.
Het opsplitsen van de applicatie in meerdere subdomeinen maakt de verwevenheid inzichtelijk en beperkt het aantal third-party dependencies per service. Dit vereenvoudigt de impact van een upgrade en maakt het uiteindelijke beheer eenvoudiger.
Onafhankelijke deployments
We hebben voor Spring Boot gekozen als basis voor deze microservice architectuur. De domeinen zijn relatief fijn gegranuleerd, wat betekent dat de uiteindelijke implementatie klein en overzichtelijk is. Een expliciete keuze voor één framework geeft eenduidigheid in onze code base wat de productiviteit ten goede komt.
Elke applicatie draait in zijn eigen virtuele omgeving, die we automatisch opbouwen. De services worden gedeployed met Rundeck en Puppet. Rundeck is verantwoordelijk voor het uitvoeren van de juiste Puppet-commando’s binnen onze private cloud instances. Dit is een integraal onderdeel van ons continuous integration proces.
Samenwerken is een must
Doordat de services autonoom draaien, wordt een deel van de verwevenheid tussen domeinen verplaatst van de traditionele monoliet naar de middleware, zoals de load balancer. Dit vraagt dus meer afstemming tussen ontwikkelaars en beheerders.
Binnen ons project staat DevOps hoog in het vaandel. Beheerders en ontwikkelaars zitten bij elkaar en kunnen continu met elkaar afstemmen. We werken op deze manier veel beter samen op het gebied van monitoring, security en optimalisatie van de verschillende applicaties in relatie tot netwerken, virtualisatie en zelfs hardware.
De samenwerking met beheer leidt tot applicaties waar de reactieve foutafhandeling snel en efficiënt wordt gedetecteerd. De volgende stap is dat onze services zelf een oplossing hebben voor een eventuele verandering in het landschap. Immers kan een afhankelijke REST service niet beschikbaar zijn. Een ander voorbeeld is een implementatie van elastische load balancing.
De heldere splitsing naar businessfunctionaliteit en domeinen schept veel duidelijkheid. Door het definiëren van specifieke interfaces en een eenduidig protocol wordt veel miscommunicatie voorkomen.
De vergaande integratie in een hoog gedistribueerde omgeving kent veel uitdagingen. Het vereist dat zowel ontwikkelaars als beheerders samenwerken om zo tot een goede oplossing te komen. Dit vergt kennis en begrip van elkaars werkveld.
De complexiteit en het feit dat we in een klein team werken, betekent dat we alles automatiseren wat we kunnen automatiseren. Dit voorkomt herhaalbare fouten en is tegelijkertijd een goede borging van onze gezamenlijk opgebouwde kennis.
Referenties:
- Openstack: http://www.openstack.org
- Kafka: http://kafka.apache.org
- Rundeck: http://rundeck.org
- Puppet: https://puppetlabs.com
- Spring boot: http://projects.spring.io/spring-boot/