ProHoster > Blogi > antaminen > Opi ottamaan mikropalvelut käyttöön. Osa 1. Spring Boot ja Docker
Opi ottamaan mikropalvelut käyttöön. Osa 1. Spring Boot ja Docker
Hei Habr.
Tässä artikkelissa haluan kertoa kokemuksestani oppimisympäristön luomisesta mikropalvelujen kokeilua varten. Kun opin jokaisen uuden työkalun, halusin aina kokeilla sitä paitsi paikallisella koneella myös realistisemmissa olosuhteissa. Siksi päätin luoda yksinkertaistetun mikropalvelusovelluksen, joka voidaan myöhemmin "peittää" kaikenlaisilla mielenkiintoisilla teknologioilla. Hankkeen päävaatimus on sen maksimaalinen toiminnallinen läheisyys todelliseen järjestelmään.
Aluksi jaoin projektin luomisen useisiin vaiheisiin:
Luo kaksi palvelua - "backend" (backend) ja "gateway" (yhdyskäytävä), pakkaa ne Docker-kuviin ja määritä ne toimimaan yhdessä
Avainsanat: Java 11, Spring Boot, Docker, kuvan optimointi
Jenkinsin ja putkilinjan määrittäminen koodin automaattista toimittamista varten klusteriin
Avainsanat: Jenkins-kokoonpano, lisäosat, erillinen konfiguraatiovarasto
Aion omistaa jokaiselle vaiheelle erillisen artikkelin.
Tämän artikkelisarjan painopiste ei ole mikropalvelujen kirjoittamisessa, vaan niiden saamisessa toimimaan yhdessä järjestelmässä. Vaikka kaikki nämä asiat ovat yleensä kehittäjän vastuun ulkopuolella, mielestäni on silti hyödyllistä tuntea ne vähintään 20% (joka, kuten tiedätte, antaa 80% tuloksesta). Jotkut ehdottoman tärkeät aiheet, kuten turvallisuus, jätetään pois tästä projektista, koska kirjoittaja ymmärtää vähän siitä, että tämä järjestelmä on luotu vain henkilökohtaiseen käyttöön. Otan mielelläni vastaan kaikki mielipiteet ja rakentava kritiikki.
Mikropalveluiden luominen
Palvelut on kirjoitettu Java 11:llä Spring Bootilla. Palvelujen välinen vuorovaikutus järjestetään REST:n avulla. Projekti sisältää vähimmäismäärän testejä (jotta myöhemmin Jenkinsissä on jotain testattavaa). Palveluiden lähdekoodi on saatavilla GitHubista: tausta и Gateway.
Jotta kunkin palvelun tila voidaan tarkistaa, niiden riippuvuuksiin on lisätty jousitoimilaite. Se luo /actuator/health-päätepisteen ja palauttaa tilan 200, jos palvelu on valmis vastaanottamaan liikennettä, tai 504, jos on ongelma. Tässä tapauksessa kyseessä on melko fiktiivinen tarkistus, koska palvelut ovat hyvin yksinkertaisia ja ylivoimaisen esteen sattuessa ne todennäköisesti jäävät kokonaan pois käytöstä kuin jäävät osittain toimiviksi. Mutta todellisissa järjestelmissä Actuator voi auttaa diagnosoimaan ongelman ennen kuin käyttäjät alkavat taistella siitä. Jos esimerkiksi tietokantaan pääsyssä on ongelmia, voimme vastata tähän automaattisesti pysäyttämällä pyyntöjen käsittelyn rikkinäisten palveluinstanssien kanssa.
Takapääpalvelu
Taustapalvelu yksinkertaisesti laskee ja palauttaa hyväksyttyjen pyyntöjen määrän.
Ohjaimen koodi:
@RestController
public class RequestsCounterController {
private final AtomicLong counter = new AtomicLong();
@GetMapping("/requests")
public Long getRequestsCount() {
return counter.incrementAndGet();
}
}
Ohjaimen testi:
@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"));
}
}
Palveluyhdyskäytävä
Yhdyskäytävä välittää pyynnön taustapalveluun täydentäen sitä seuraavilla tiedoilla:
yhdyskäytävän tunnus. Sitä tarvitaan, jotta yhdyskäytävän ilmentymä voidaan erottaa toisesta palvelimen vastauksen perusteella
Jokin "salaisuus", joka toimii erittäin tärkeänä salasanana (tärkeän evästeen salausavaimen numero)
$ curl http://localhost:8080/
Number of requests 1 (gateway 38560358, secret "default-secret")
Kaikki toimii. Huomaavainen lukija huomaa, että mikään ei estä meitä pääsemästä suoraan taustajärjestelmään ohittaen yhdyskäytävän (http://localhost:8081/requests). Tämän korjaamiseksi palvelut on yhdistettävä yhdeksi verkkoksi ja vain yhdyskäytävän tulee "ulkoutua" ulkopuolelle.
Lisäksi molemmat palvelut jakavat yhden tiedostojärjestelmän, tuottavat streameja ja voivat alkaa häiritä toisiaan. Olisi mukavaa eristää mikropalvelumme. Tämä voidaan saavuttaa jakamalla sovelluksia eri koneille (paljon rahaa, vaikeaa), käyttämällä virtuaalikoneita (resurssiintensiivinen, pitkä käynnistys) tai käyttämällä konttia. Kuten odotettiin, valitsemme kolmannen vaihtoehdon ja Satamatyöläinen työkaluna konttien käsittelyyn.
Satamatyöläinen
Lyhyesti sanottuna Docker luo eristettyjä säiliöitä, yhden sovellusta kohden. Dockerin käyttämiseksi sinun on kirjoitettava Dockerfile - ohjeet sovelluksen rakentamiseen ja suorittamiseen. Seuraavaksi voit rakentaa kuvan, ladata sen kuvarekisteriin (nro. Dockerhub) ja ota mikropalvelusi käyttöön missä tahansa telakoidussa ympäristössä yhdellä komennolla.
Dockerfile
Yksi kuvan tärkeimmistä ominaisuuksista on sen koko. Kompakti kuva latautuu nopeammin etävarastosta, vie vähemmän tilaa ja palvelusi käynnistyy nopeammin. Mikä tahansa kuva rakennetaan peruskuvan perusteella, ja on suositeltavaa valita minimalistisin vaihtoehto. Hyvä vaihtoehto on Alpine, täydellinen Linux-jakelu minimaalisilla paketeilla.
Aluksi yritetään kirjoittaa Docker-tiedosto "otsaan" (sanoan heti, että tämä on huono tapa, älä tee sitä):
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"]
Tässä käytämme Alpine-pohjaista peruskuvaa, jossa JDK on jo asennettu projektin rakentamiseen. ADD-komennolla lisäämme kuvan nykyisen src-hakemiston, merkitsemme sen toimivaksi (WORKDIR) ja aloitamme rakentamisen. EXPOSE 8080 -komento ilmoittaa dockerille, että säiliössä oleva sovellus käyttää porttiaan 8080 (tämä ei tee sovellusta saatavaa ulkopuolelta, mutta mahdollistaa sovelluksen käytön esimerkiksi toisesta saman telakointiverkoston kontista ).
Jos haluat pakata palvelut kuviksi, sinun on suoritettava komennot kunkin projektin juuresta:
docker image build . -t msvc-backend:1.0.0
Tuloksena on 456 Mt:n kuva (josta JDK-peruskuva vei 340 Mt). Ja kaikki siitä huolimatta, että projektimme luokat voidaan laskea sormella. Voit pienentää kuvamme kokoa seuraavasti:
Käytämme monivaiheista kokoonpanoa. Ensimmäisessä vaiheessa rakennamme projektin, toisessa vaiheessa asennamme JRE:n ja kolmannessa vaiheessa kopioimme kaiken uuteen puhtaaseen Alpine-imagoon. Yhteensä vain tarvittavat komponentit ovat lopullisessa kuvassa.
Käytetään Java:n modularisointia. Java 9:stä alkaen voit käyttää jlink-työkalua JRE:n luomiseen vain tarvitsemistasi moduuleista
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"]
Luomme kuvan uudelleen, ja sen seurauksena se menetti 6 kertaa painoaan eli 77 Mt. Ei paha. Tämän jälkeen valmiita kuvia voidaan ladata kuvarekisteriin, jotta kuvat ovat ladattavissa Internetistä.
Yhteiskäyttöpalvelut Dockerissa
Aluksi palveluidemme on oltava samassa verkossa. Dockerissa on useita verkkotyyppejä, ja käytämme niistä alkeellisinta - siltaa, jonka avulla voit verkottaa samassa isännässä toimivia säiliöitä. Luo verkko seuraavalla komennolla:
docker network create msvc-network
Käynnistä seuraavaksi backend-säilö nimeltä "backend" microservices-backend:1.0.0-kuvalla:
docker run -dit --name backend --network msvc-net microservices-backend:1.0.0
On syytä huomata, että siltaverkko tarjoaa käyttövalmiin palvelun etsinnän konteille niiden nimien perusteella. Eli taustapalvelu on saatavilla telakointiverkon sisällä osoitteessa http://backend:8080.
Tässä komennossa osoitamme, että välitämme isäntämme portin 80 kontin porttiin 8080. Käytämme env-asetuksia asettaaksemme ympäristömuuttujia, jotka jousi lukee automaattisesti ja jotka ohittavat ominaisuudet tiedostosta application.properties.
Aloittamisen jälkeen soitamme http://localhost/ ja varmista, että kaikki toimii, kuten edellisessä tapauksessa.
Johtopäätös
Lopputuloksena loimme kaksi yksinkertaista mikropalvelua, pakkasimme ne telakointisäiliöihin ja käynnistimme ne yhdessä samassa koneessa. Tuloksena olevalla järjestelmällä on kuitenkin useita haittoja:
Huono vikasietoisuus - kaikki toimii meillä yhdellä palvelimella
Huono skaalautuvuus - kuormituksen kasvaessa olisi mukava ottaa automaattisesti käyttöön lisäpalveluinstanssit ja tasapainottaa niiden välinen kuormitus
Käynnistyksen monimutkaisuus - meidän piti antaa vähintään 3 komentoa ja tietyillä parametreilla (tämä koskee vain kahta palvelua)
Yllä olevien ongelmien korjaamiseksi on olemassa useita ratkaisuja, kuten Docker Swarm, Nomad, Kubernetes tai OpenShift. Jos koko järjestelmä on kirjoitettu Javalla, voit katsoa kohti Spring Cloudia (hyvä artikkeli).
В seuraava osa Puhun siitä, kuinka otin Kubernetesin käyttöön ja otin projektin käyttöön Google Kubernetes Enginessä.