Microservice bauen
In Anlehnung an das Microservices Lab von Eberhard Wolff am 8.11.2016 auf der W-JAX in München.Minimaler REST-Service bauen
Einen Spring-Boot "Hello World!"-REST-Service bauen. Das kann man mit Spring Initializr machen oder per Hand.Wenn das Projekt mit Spring Initialzr erzeugt wurde, dann einfach downloaden, entpacken und in eine IDE deiner Wahl importieren.
Anschließend eine Klasse für den REST-Service implementieren:
@RestController @EnableAutoConfigurationpublic class HelloWorldController { @RequestMapping(path = "/") public String helloWorld() { return "Hello World!"; } }
Dann das Projekt bauen und testen:
curl localhost:8080
Als Antwort sollte dann
Hello World!
kommen.
Jetzt wird der Microservice als JAR-Datei erzeugt mvn package, gestartet java -jar target/hello-world-0.0.1-SNAPSHOT.jar und nochmal getestet.
Referenzen
Monitoring einbauen
Spring Boot bietet ein gutes Monitoring mit Hilfe der vorbereiteten Acutators. Einfach in die POM einbauen.<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
Anwendung neu starten und abfragen:
curl localhost:8080/health | json_pp
Dann sollte so etwas rauskommen:
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 105 0 105 0 0 6794 0 --:--:-- --:--:-- --:--:-- 7000
{
"diskSpace" : {
"total" : 243045949440,
"free" : 223517011968,
"status" : "UP",
"threshold" : 10485760
},
"status" : "UP"
}
Ein weiterer interessanter Endpoint ist:
curl localhost:8080/metrics | json_pp
Dort kann man ablesen, welcher Service wie oft aufgerufen wurde.
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 838 0 838 0 0 838 0 --:--:-- --:--:-- --:--:-- 818k
{
"nonheap.init" : 2496,
"nonheap.used" : 50635,
"httpsessions.active" : 0,
"gc.ps_marksweep.time" : 32,
"httpsessions.max" : -1,
"gc.ps_marksweep.count" : 1,
"counter.status.200.info" : 1,
"counter.status.200.beans" : 1,
"gauge.response.metrics" : 0,
"classes" : 6134,
"heap.init" : 131072,
"threads.daemon" : 21,
"gauge.response.health" : 8,
"systemload.average" : -1,
"counter.status.200.health" : 3,
"threads.totalStarted" : 27,
"threads" : 23,
"threads.peak" : 23,
"mem.free" : 224805,
"nonheap.committed" : 53696,
"gauge.response.beans" : 38,
"heap.used" : 55770,
"gc.ps_scavenge.time" : 77,
"counter.status.200.metrics" : 4,
"instance.uptime" : 982970,
"nonheap" : 0,
"uptime" : 985825,
"processors" : 4,
"gauge.response.info" : 19,
"gauge.response.root" : 255,
"counter.status.200.root" : 1,
"classes.unloaded" : 0,
"mem" : 331211,
"heap.committed" : 280576,
"classes.loaded" : 6134,
"gc.ps_scavenge.count" : 8,
"heap" : 1853440
}
Referenzen
Dockerfile bauen
Annahme: Wir laufen unter Linux und Docker ist bereits installiert.Jetzt können wir die Anwendung in ein Docker Image einpacken. Dazu benötigen wir ein Dockerfile, das wir in das Verzeichnis hello-world legen. Die Datei heißt Dockerfile und hat folgenden Inhalt:
FROM openjdk:8
ADD target/hello-world-0.0.1-SNAPSHOT.jar .
CMD /usr/bin/java -Xmx400m -Xms400m -jar hello-world-0.0.1-SNAPSHOT.jar
EXPOSE 8080
Beschreibung:
(1) FROM beschreibt das Docker Image von dem wir ausgehen. Docker Hub bietet eine Reihe von vorbereitetes Images an. Wir benötigen nur ein, das schon ein Java drin hat. Ich habe mir hier für OpenJDK 8 entschieden.
(2) ADD beschreibt was zusätzlich in den Container eingepackt werden soll. In diesem Fall unsere fertige Applikation.
(3) CMD ist das Kommando, das beim Start des Containers ausgeführt werden soll. Bei uns soll automatisch die Applikation gestartet werden.
(4) EXPOSE beschreibt welcher Port des Containers nach außen verfügbar sein soll.
Das Docker Image wird jetzt mit folgendem Kommando gebaut, wobei wir uns eine Verzeichnisebene außerhalb unseres hello-world Projekts befinden.
sudo docker build -t <tag> <verzeichnis>
sudo docker build -t helloworld hello-world
Ist die folgende Schreibweise eine Abkürzung oder gehört sie zu einer anderen Docker Version?
sudo docker --build=<tag> <verzeichnis>
sudo docker --build=helloworld hello-world
Jetzt lassen wir uns zeigen, ob Docker unser Image kennt
sudo docker images
Dann sollte folgendes gezeigt werden:
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld latest e00d323fce30 57 minutes ago 657.9 MB
openjdk 8 861e95c114d6 4 weeks ago 643.2 MB
Wollen wir nochmal anschauen, was alles in unserem Image drin ist, geht das mit
sudo docker history <tag>
sudo docker history helloworld
Dann erscheint bei mir:
IMAGE CREATED CREATED BY SIZE COMMENT
e00d323fce30 57 minutes ago /bin/sh -c #(nop) EXPOSE 8080/tcp 0 B
6f7c12b9ddac 57 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "/usr/ 0 B
298395009277 57 minutes ago /bin/sh -c #(nop) ADD file:aa4a274215e0f5109f 14.67 MB
861e95c114d6 4 weeks ago /bin/sh -c /var/lib/dpkg/info/ca-certificates 418.2 kB
<missing> 4 weeks ago /bin/sh -c set -x && apt-get update && apt- 351.5 MB
<missing> 4 weeks ago /bin/sh -c #(nop) ENV CA_CERTIFICATES_JAVA_V 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ENV JAVA_DEBIAN_VERSION=8u 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ENV JAVA_VERSION=8u111 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ENV JAVA_HOME=/usr/lib/jvm 0 B
<missing> 4 weeks ago /bin/sh -c { echo '#!/bin/sh'; echo 'set 87 B
<missing> 4 weeks ago /bin/sh -c #(nop) ENV LANG=C.UTF-8 0 B
<missing> 4 weeks ago /bin/sh -c echo 'deb http://deb.debian.org/de 55 B
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install 1.287 MB
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install 122.6 MB
<missing> 4 weeks ago /bin/sh -c apt-get update && apt-get install 44.3 MB
<missing> 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:41ea5187c50116884c 123 MB
Jetzt starten wir unser Docker Image mit dem Kommando:
sudo docker run <tag>
sudo docker run helloworld
Dann sollten gleich die Logausgaben unserer Anwendung erscheinen. Am Ende der Logausgaben sehen wir:
Tomcat started on port(s): 8080 (http)
Damit ist jetzt der Port 8080 im Container gemeint. Wir können also nicht mit "curl localhost:8080" auf die Anwendung zugreifen, weil die Anwendung jetzt im Container läuft.
Wenn wir jetzt auf unsere Anwendung zugreifen wollen, müssen wir zuerst die Instanz finden und dann die IP-Adresse herausfinden. Um zu sehen, welche Docker Images laufen, benutzen wir
sudo docker ps
Damit bekommen wir die laufenden Docker Images gezeigt:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
17ef7c5b7462 helloworld "/bin/sh -c '/usr/bin" 22 seconds ago Up 21 seconds 8080/tcp sad_minsky
Die Container ID ist jetzt besonders wichtig. Nur damit können wir auf die laufende Docker Instanz zugreifen. Wir wollen nun herausfinden, auf welcher IP-Adresse diese Instanz läuft:
sudo docker inspect --format '{{ .NetworkSettings.IPAddress }}' 17ef7c5b7462
Ich bekomme als Ergebnis
172.17.0.2
Jetzt kann ich mit
curl 172.17.0.2:8080
auf meine Anwendung zugreifen.
Jetzt kann ich meinen Container wieder stoppen, auch nur mit der Container ID.
sudo docker stop 17ef7c5b7462
Keine Kommentare:
Kommentar veröffentlichen