ProHoster > Blog > Adminisztráció > Ismerje meg a mikroszolgáltatások üzembe helyezését. 1. rész. Spring Boot és Docker
Ismerje meg a mikroszolgáltatások üzembe helyezését. 1. rész. Spring Boot és Docker
Szia Habr.
Ebben a cikkben a mikroszolgáltatásokkal való kísérletezéshez szükséges tanulási környezet létrehozásával kapcsolatos tapasztalataimról szeretnék beszélni. Amikor minden új eszközt megtanultam, nem csak a helyi gépen szerettem volna kipróbálni, hanem reálisabb körülmények között is. Ezért úgy döntöttem, hogy létrehozok egy egyszerűsített mikroszolgáltatási alkalmazást, amelyet később mindenféle érdekes technológiával "be lehet borítani". A projekt fő követelménye a valós rendszerhez való maximális funkcionális közelség.
Kezdetben a projekt létrehozását több lépésre bontottam:
Hozzon létre két szolgáltatást – 'backend' (backend) és 'gateway' (gateway), csomagolja docker képekbe, és állítsa be őket, hogy működjenek együtt
Kulcsszavak: Java 11, Spring Boot, Docker, képoptimalizálás
Diagram készítése a Helm 3 segítségével a jobb fürtkezelés érdekében
Címkék: Helm 3, diagram telepítés
A Jenkins és a folyamat beállítása a kódnak a fürtbe történő automatikus kézbesítéséhez
Kulcsszavak: Jenkins konfiguráció, bővítmények, külön konfigurációs tároló
Minden lépésnek külön cikket tervezek szentelni.
Ennek a cikksorozatnak a középpontjában nem a mikroszolgáltatások megírása áll, hanem az, hogyan tegyük őket egyetlen rendszerben működőképessé. Bár ezek a dolgok általában kívül esnek a fejlesztő felelősségén, mégis hasznosnak tartom, ha legalább 20%-ban ismerkedsz velük (ami, mint tudod, az eredmény 80%-át adja). Néhány feltétel nélkül fontos téma, mint például a biztonság, kimarad ebből a projektből, mivel a szerző keveset ért arról, hogy ez a rendszer kizárólag személyes használatra készült. Minden véleményt és építő kritikát szívesen fogadok.
Mikroszolgáltatások létrehozása
A szolgáltatásokat Java 11-ben írták a Spring Boot segítségével. A szolgálatok közötti interakció a REST segítségével szerveződik. A projekt tartalmazni fog egy minimális számú tesztet (hogy később legyen mit tesztelni Jenkinsben). A szolgáltatások forráskódja elérhető a GitHubon: backend и Átjáró.
Annak érdekében, hogy ellenőrizni lehessen az egyes szolgáltatások állapotát, egy rugós működtetőt adtunk hozzá a függőségeikhez. Létrehoz egy /actuator/health végpontot, és 200-as állapotot ad vissza, ha a szolgáltatás készen áll a forgalom fogadására, vagy 504-et, ha probléma van. Jelen esetben ez egy meglehetősen fiktív ellenőrzés, mivel a szolgáltatások nagyon egyszerűek, és valamilyen vis maior esetén nagyobb valószínűséggel válnak teljesen elérhetetlenné, mintsem részben működjenek. A valós rendszerekben azonban az Actuator segíthet a probléma diagnosztizálásában, mielőtt a felhasználók elkezdenének küzdeni vele. Például, ha problémák merülnek fel az adatbázis elérésével, akkor automatikusan reagálhatunk erre úgy, hogy leállítjuk a meghibásodott szolgáltatáspéldány esetén a kérések feldolgozását.
Hátsó szolgáltatás
A háttérszolgáltatás egyszerűen megszámolja és visszaadja az elfogadott kérések számát.
Vezérlő kód:
@RestController
public class RequestsCounterController {
private final AtomicLong counter = new AtomicLong();
@GetMapping("/requests")
public Long getRequestsCount() {
return counter.incrementAndGet();
}
}
Vezérlő teszt:
@WebMvcTest(RequestsCounterController.class)
public class RequestsCounterControllerTests {
@Autowired
private MockMvc mockMvc;
@Test
public void firstRequest_one() throws Exception {
mockMvc.perform(get("/requests"))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.content().string("1"));
}
}
Service Gateway
Az átjáró továbbítja a kérést a háttérszolgáltatásnak, kiegészítve azt a következő információkkal:
átjáró azonosítója. Erre azért van szükség, hogy a szerver válasza alapján meg lehessen különböztetni az átjáró egyik példányát a másiktól
Valami "titok", amely egy nagyon fontos jelszó szerepét tölti be (egy fontos cookie titkosítási kulcsának száma)
$ curl http://localhost:8080/
Number of requests 1 (gateway 38560358, secret "default-secret")
Minden működik. Egy figyelmes olvasó megjegyzi, hogy semmi sem akadályoz meg bennünket abban, hogy közvetlenül hozzáférjünk a háttérrendszerhez, megkerülve az átjárót (http://localhost:8081/requests). Ennek kijavításához a szolgáltatásokat egy hálózatba kell egyesíteni, és kívülről csak az átjáró "lógjon ki".
Ezenkívül mindkét szolgáltatás egy fájlrendszeren osztozik, adatfolyamokat hoz létre, és egy pillanat alatt interferálhatnak egymással. Jó lenne elkülöníteni a mikroszolgáltatásainkat. Ezt úgy érhetjük el, hogy alkalmazásokat terjesztünk különböző gépeken (sok pénz, nehéz), virtuális gépeket használunk (erőforrásigényes, hosszú indítás), vagy konténerezést alkalmazunk. A várakozásoknak megfelelően a harmadik lehetőséget választjuk és Dokkmunkás konténerezés eszközeként.
Dokkmunkás
Röviden, a docker izolált tárolókat hoz létre, alkalmazásonként egyet. A docker használatához meg kell írnia egy Dockerfile-t - utasításokat az alkalmazás felépítéséhez és futtatásához. Ezután összeállíthatja a képet, feltöltheti a képregisztrációba (No. Dockerhub), és egyetlen paranccsal telepítse a mikroszolgáltatást bármely dokkolós környezetben.
dockerfile
A kép egyik legfontosabb jellemzője a mérete. A kompakt kép gyorsabban töltődik le egy távoli adattárból, kevesebb helyet foglal el, és a szolgáltatás gyorsabban indul el. Bármely kép az alapkép alapján épül fel, és ajánlatos a legminimálisabb opciót választani. Jó lehetőség az Alpine, egy komplett Linux disztribúció minimális csomagokkal.
Először is próbáljunk meg egy Dockerfile-t írni "a homlokra" (azonnal mondom, hogy ez rossz út, ne tedd):
FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests
EXPOSE 8080
ENTRYPOINT ["java","-jar","target/microservices-gateway-1.0.0.jar"]
Itt egy Alpine alapú alapképet használunk a már telepített JDK-val a projektünk elkészítéséhez. Az ADD paranccsal hozzáadjuk az aktuális src könyvtárat a képhez, megjelöljük működőként (WORKDIR) és elindítjuk a buildet. Az EXPOSE 8080 parancs jelzi a dockernek, hogy a konténerben lévő alkalmazás a 8080-as portját fogja használni (ez nem teszi elérhetővé az alkalmazást kívülről, de lehetővé teszi az alkalmazás elérését például egy másik konténerről ugyanazon a docker hálózaton ).
A szolgáltatások képekbe csomagolásához parancsokat kell futtatnia az egyes projektek gyökeréből:
docker image build . -t msvc-backend:1.0.0
Az eredmény egy 456 MB-os kép (ebből az alap JDK-kép 340 MB-ot foglalt el). És mindez annak ellenére, hogy a projektünkben szereplő osztályok egy ujjon megszámolhatók. Képünk méretének csökkentése:
Többlépcsős összeszerelést alkalmazunk. Első lépésben megépítjük a projektet, második lépésben a JRE-t telepítjük, a harmadik lépésben pedig az egészet átmásoljuk egy új tiszta Alpine image-be. Összességében csak a szükséges alkatrészek lesznek a végső képen.
Használjuk a java modularizációját. A Java 9-től kezdve használhatja a jlink eszközt JRE létrehozására csak a szükséges modulokból
FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine as builder
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests
FROM alpine:3.10.3 as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink
--verbose
--add-modules
java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument
--compress 2 --strip-debug --no-header-files --no-man-pages
--release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE"
--output "$JAVA_MINIMAL"
FROM alpine:3.10.3
LABEL maintainer="Anton Shelenkov [email protected]"
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY --from=builder /src/target/microservices-backend-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]
Újra létrehoztuk a képet, és ennek eredményeként súlyának hatszorosát veszítette, ami 6 MB-ot jelent. Nem rossz. Ezt követően a kész képek feltölthetők a képnyilvántartásba, így a képei letölthetők az internetről.
Együttműködő szolgáltatások a Dockerben
Először is szolgáltatásainknak ugyanazon a hálózaton kell lenniük. A dockerben többféle hálózat létezik, és ezek közül a legprimitívebbet használjuk - a bridge-et, amely lehetővé teszi az ugyanazon a gazdagépen futó konténerek hálózati használatát. Hozzon létre egy hálózatot a következő paranccsal:
docker network create msvc-network
Ezután indítsa el a „backend” nevű háttértárolót a microservices-backend:1.0.0 képpel:
docker run -dit --name backend --network msvc-net microservices-backend:1.0.0
Érdemes megjegyezni, hogy a hídhálózat azonnali szolgáltatás-felderítést biztosít a konténerek nevük alapján. Vagyis a háttérszolgáltatás elérhető lesz a docker-hálózaton belül a címen http://backend:8080.
Ebben a parancsban azt jelezzük, hogy a gazdagépünk 80-as portját a tároló 8080-as portjára továbbítjuk. Az env beállításokat használjuk a környezeti változók beállítására, amelyeket a rugó automatikusan beolvas, és felülbírálja az application.properties tulajdonságait.
Indítás után hívjuk http://localhost/ és győződjön meg arról, hogy minden működik, mint az előző esetben.
Következtetés
Ennek eredményeként két egyszerű mikroszolgáltatást hoztunk létre, ezeket docker konténerekbe csomagoltuk, és együtt indítottuk el ugyanazon a gépen. Az így létrejött rendszernek azonban számos hátránya van:
Gyenge hibatűrés - minden működik nekünk egy szerveren
Rossz skálázhatóság – ha a terhelés növekszik, jó lenne automatikusan telepíteni további szolgáltatáspéldányokat, és kiegyenlíteni a terhelést közöttük
Az indítás összetettsége - legalább 3 parancsot kellett megadnunk, és bizonyos paraméterekkel (ez csak 2 szolgáltatásra vonatkozik)
A fenti problémák megoldására számos megoldás létezik, például a Docker Swarm, a Nomad, a Kubernetes vagy az OpenShift. Ha az egész rendszer Java nyelven van írva, akkor a Spring Cloud felé nézhet (jó cikk).
В következő rész Beszélni fogok arról, hogyan állítottam be a Kuberneteset, és hogyan telepítettem a projektet a Google Kubernetes Engine-be.