In dit artikel behandel ik de mogelijkheden die Jhipster biedt om een microservice architectuur op te zetten. Jhipster is een generator om een Spring boot / angular applicatie te genereren. In een voorgaand artikel (Java Magazine 2016-03) kun je nog meer lezen over de mogelijkheden van Jhipster in de monolithische vorm.
Ben Ooms
Behalve het snel opzetten van een monoliet biedt Jhipster ook de mogelijkheid om een complete microservice architectuur op te zetten. Jhipster levert een microservice chassis waarop je snel microservices kunt bouwen zonder al te veel tijd kwijt te zijn aan zaken, zoals service registry, centrale configuratie, centrale monitoring en load balancing. Op afbeelding 1 zie je hier een grafische weergave van. Jhipster is niet een framework dat dit regelt, maar een combinatie van gevestigde open source dat frameworks met elkaar combineert. Je kunt het vergelijken met Spring boot. Spring boot zelf is geen framework, maar combineert frameworks met een default configuratie om hier snel mee aan de slag te gaan.
De architectuur bestaat uit een gateway, registry, console en optioneel een identity en access management server. Standaard biedt Jhipster ook een goede ondersteuning voor Docker en wordt voor de services standaard een Docker file gegenereerd. In een Jhipster microservice omgeving heeft Jhipster een docker-compose generator die je kunt gebruiken om voor alle services een docker-compose file te genereren.
De API gateway is in de basis een reguliere Jhipster applicatie. Je kunt deze configureren, zoals je dit zou doen voor een monoliet. De functie van de gateway is om als ingang te dienen voor de onderliggende microservices. Het biedt http routing, load balancing, security en het host ook de API documentatie van de onderliggende microservices. Je wordt door Jhipster niet beperkt in het aantal gateways. Je kunt er meer dan één gebruiken in je architectuur. Voor de load balancing wordt gebruik gemaakt van Netflix Ribbon.
De gateway biedt automatische documentatie van de microservices door gebruik te maken van Swagger. Daarnaast kunnen de routes van de gateway gemonitord worden. Optioneel biedt de gateway ook rate limiting, al moet je hiervoor een cassandra cluster beschikbaar hebben.
Voor de security tussen de gateway en de onderliggende services gebruikt Jhipster JWT. JWT staat voor Json web token. Jhipster gebruikt de JJWT library. Voor wie niet weet wat JWT inhoudt, even een korte opfrisser. JWT biedt de mogelijkheid om informatie op een compacte en verifieerbare manier te delen. De informatie die door middel van JWT wordt gedeeld, bestaat uit een Json object met zogenoemde claims. JWT tokens worden cryptografisch getekend. Het werken met JWT tokens zorgt ervoor dat alle security informatie gedeeld kan worden tussen de services en dat de services alle informatie hebben om vast te stellen of een resource beschikbaar is voor de bewuste call, zonder hiervoor andere calls te doen. Dit is natuurlijk in een microservice architectuur zeer belangrijk voor de schaalbaarheid. Standaard zijn alle microservice eindpunten beschikbaar via de gateway. De gateway biedt de mogelijkheid om dit op globaal niveau te configureren. Meer informatie over JWT kan je vinden op http://jwt.io.
De registry is een standaard runtime service die Jhipster biedt. Deze biedt de mogelijkheid voor de services om zich te registreren en om een centrale toegang te bieden tot configuratie gegevens. Als basis worden twee smaken aangeboden, de ene is op basis van Consul en de andere is gebaseerd op een combinatie van Netflix Eureka en Spring Cloud Config. De registry is standaard beveiligd. Voor de configuratie gegevens heb je de keuze uit twee mogelijkheden, native en Git. Met de native variant wordt het onderliggende filesysteem gebruikt voor de opslag van configuratiegegevens en met de Git variant gaat dit in een Git repository.
De Jhipster console is een standard ELK stack waar de microservices automatisch de logging naartoe sturen. Ook zijn standaard een aantal Kibana dashboards beschikbaar. Om de Jhipster microservice architectuur beter te leren kennen, gaan we een simpel voorbeeld van een microservice architectuur uitwerken. In dit voorbeeld willen we een service neerzetten voor een fictief autoverhuurbedrijf. We willen een service voor autogegevens. Als we die service hebben, gaan we deze beschikbaar maken door middel van een gateway. Verder willen we dat de service in de Jhipster registry en console bekend zijn. Onze architectuur zal Docker based zijn en is door middel van Docker-compose te starten.
Voorbeeld
Het is belangrijk dat alle services van onze architectuur in dezelfde hoofdmap zitten. De reden hiervoor is dat dit het genereren van de Docker-compose file gemakkelijk maakt. Om te beginnen gaan we eerst de registry opzetten. Na een git clone vanuit https://github.com/jhipster/jhipster-registry kan je in de map van de registry het commando “mvn spring-boot:run” uitvoeren en heb je een werkende registry die te benaderen is op http://localhost:8761.
De standaard inlognaam is “admin” met wachtwoord “admin”.
Als tweede gaan we een gateway genereren die straks onze services beschikbaar maakt. Hiervoor maak je een map aan genaamd ‘gateway’ en start je de generatie van een Jhipster applicatie met “yo jhipster”. Voor een gateway kies je de volgende opties (gebruik de voorgestelde default voor de niet genoemde opties):
- Type of application
- Microservice gateway
- Authentication to use
- JWT
- Service discovery
- JHipster Registry (using Eureka and Spring Cloud Config)
- Type of database
- SQL
- mysql
Na de generatie is de gateway te starten met “mvn spring-boot:run” en te benaderen op “http://localhost:8080”. Als je de registry nog heb laten draaien, is de gateway ook zichtbaar in de registry onder instances. Om de gateway die we net gegenereerd hebben ook als Docker image beschikbaar te maken, moeten we ook “mvn package -Pprod docker:build” aanroepen.
De console is beschikbaar als Docker image. We gaan deze toevoegen aan onze architectuur door een start te maken met docker-compose.
De stappen zijn:
- Maak een map aan voor Docker-compose;
- Roep binnen de net aangemaakte map “yo jhipster:docker-compose”;
- Gebruik de volgende opties:
- type of applications to deploy
- Microservice
- Root directory
- De default, ../
- Selecteer de gateway
- Setup monitoring
- Yes, ELK based
- type of applications to deploy
Nu kunnen we de infrastructuur testen met “docker-compose up -d”. Vergeet niet om eerst de services te stoppen die je eerder getest hebt. Na het starten zijn de registry, console en de gateway beschikbaar en te gebruiken. Nu we een werkende architectuur hebben, kunnen we aan onze services beginnen.
Services met Jhipster genereren, werkt op dezelfde manier als wanneer je een monoliet genereert. Bijna alle opties kunnen gebruikt worden. Interessant om te vermelden is dat, wanneer je een microservice genereert in plaats van een monoliet, je ook een microservice kunt genereren zonder database. Dit is heel handig om Jhipster ready microservices te maken die als brug fungeren richting legacy systemen.
Voor de autogegevens gaan we een service maken met een database backend. We zullen deze carbase noemen. Het model van carbase is heel simpel en doormiddel van JDL studio (https://jhipster.github.io/jdl-studio/) kunnen we het model definiëren, zoals ook op afbeelding 2 te zien is. De microservice zal alleen een backend vormen en de front end zal in de gateway komen. Om dit te doen, zullen we een nieuwe service genereren en de bestaande gateway updaten met de front end.
Om de service te maken, voer je onderstaande stappen uit:
- Maak in de hoofdmap van het project een map carbase aan;
- Voer in de carbase map het commando “yo jhipster”;
- Selecteer de opties “microservice application”, “JWT authentication”, “Jhipster registry”;
- Kopieer het jdl bestand vanuit de studio en plaats deze in de carbase map;
- Voer het commando “yo jhipster:import-jdl <<bestandsnaam>>”;
- Voer het commando “mvn package -Pprod docker:build”.
We hebben nu de carbase service gecreëerd en een dockerfile gegenereerd. Als je “mvn spring-boot:run” uitvoert kun je via de url “http://localhost:8081/v2/api-docs” de car en category endpoint vinden, deze zijn ook beveiligd.
Om de front-end te genereren, moeten we de gateway bijwerken. Dit doen we door de entiteiten aan te maken.
- Voer het commando “yo jhipster:entity car”;
- Kies voor microservices;
- Voer de mapnaam van de carbase service (../carbase);
- Doe hetzelfde voor de category entiteit;
- Voer het commando “mvn package -Pprod docker:build”.
Als we nu in de docker-compose map “yo jhipster:docker-compose” uitvoeren, zullen we de carbase en de nieuwe gateway kunnen bijwerken. Als we nu “docker-compose up -d” uitvoeren, zul je in de gateway de front-end van de car en category kunnen gebruiken. De registry zal twee services tonen en ook in Kibana zul je metrics vinden van beide services. In Kibana zijn pre-geconfigureerde dashboards te vinden onder dashboards->open. Ook zijn de services schaalbaar, probeer maar “docker-compose scale carbase-app=2” uit. Je zal even later in de registry en in de Kibana console twee instanties tegenkomen van de carbase applicatie. Daarnaast kun je de services ook vinden in de gateway. Elke gateway heeft in het “administration” menu een gateway pagina waar alle routes in vermeld staan. Voor de carbase zouden dit er nu twee moeten zijn.
Tot slot
Zoals je kunt zien, is het erg eenvoudig om een microservice infrastructuur neer te zetten met Jhipster. Het biedt je de tools om snel een concept uit te werken tot een complete basis. We hebben hier alleen de basis besproken. De features die we niet besproken hebben, zijn onder andere de verschillende opties en keuzes die je hebt wanneer je de infrastructuur opzet, gedistribueerde tracing waar Zipkin voor gebruikt wordt en de verschillende manieren om naar productie te gaan in een cloud omgeving, zoals Cloud foundry en Heroku. Ook heb ik hier de UAA server niet besproken.
Wat ik in het algemeen interessant vind aan Jhipster is dat je er veel van kan leren wanneer je dezelfde frameworks gebruikt als Jhipster. Daarnaast biedt het een ideale basis om snel concepten uit te werken, nu zelfs met een stuk microservice architectuur. In het dagelijkse werk heb ik vaak gekeken in de Jhipster source code hoe bepaalde zaken opgepakt waren en deze als basis gebruikt in mijn eigen projecten.