Микро үйлчилгээг хэрхэн ашиглах талаар суралц. 1-р хэсэг. Spring Boot болон Docker

Микро үйлчилгээг хэрхэн ашиглах талаар суралц. 1-р хэсэг. Spring Boot болон Docker

Хөөе Хабр.

Энэ нийтлэлд би микро үйлчилгээг туршиж үзэх сургалтын орчныг бүрдүүлэх туршлагаасаа ярихыг хүсч байна. Би шинэ хэрэгсэл бүрийг сурахдаа үүнийг зөвхөн орон нутгийн машин дээр төдийгүй илүү бодит нөхцөлд туршиж үзэхийг үргэлж хүсдэг байв. Тиймээс би хялбаршуулсан микро үйлчилгээний програмыг бүтээхээр шийдсэн бөгөөд үүнийг дараа нь бүх төрлийн сонирхолтой технологиор "бүрхэж" болно. Төсөлд тавигдах гол шаардлага бол бодит системд хамгийн их функциональ ойр байх явдал юм.

Эхэндээ би төслийг бүтээх ажлыг хэд хэдэн үе шат болгон хуваасан.

  1. 'backend' (backend) болон 'gateway' (gateway) гэсэн хоёр үйлчилгээг үүсгэж, тэдгээрийг докерын зурагт багцалж, хамтдаа ажиллахаар тохируулна уу.

    Түлхүүр үг: Java 11, Spring Boot, Docker, image optimization

  2. Google Kubernetes Engine-д Kubernetes тохиргоо болон системийн байршуулалтыг хөгжүүлэх

    Түлхүүр үг: Kubernetes, GKE, нөөцийн удирдлага, автомат масштаб, нууц

  3. Кластерийг илүү сайн удирдахын тулд Helm 3 ашиглан диаграмм үүсгэх

    Шошго: Helm 3, диаграмын байршуулалт

  4. Кластерт кодыг автоматаар хүргэхийн тулд Jenkins болон дамжуулах хоолойг тохируулах

    Түлхүүр үг: Женкинсийн тохиргоо, залгаасууд, тусдаа тохиргооны агуулах

Би алхам бүрт тусдаа нийтлэл зориулахаар төлөвлөж байна.

Энэхүү цуврал нийтлэлийн гол зүйл бол микро үйлчилгээг хэрхэн бичих тухай биш харин тэдгээрийг нэг системд хэрхэн ажиллуулах тухай юм. Хэдийгээр эдгээр бүх зүйл нь ихэвчлэн хөгжүүлэгчийн үүрэг хариуцлагаас гадуур байдаг ч хамгийн багадаа 20% (энэ нь үр дүнгийн 80% -ийг өгдөг) тэдэнтэй танилцах нь ашигтай хэвээр байна гэж би бодож байна. Аюулгүй байдал гэх мэт болзолгүй чухал сэдвүүд энэ төслийн гадна үлдэх болно, учир нь зохиогч энэ системийг зөвхөн хувийн хэрэгцээнд зориулан бүтээсэн талаар бага ойлголттой байдаг. Би аливаа санал бодол, бүтээлч шүүмжлэлд баяртай байна.

Микро үйлчилгээ бий болгох

Үйлчилгээг Spring Boot ашиглан Java 11 дээр бичсэн. Үйлчилгээ хоорондын харилцан үйлчлэлийг REST ашиглан зохион байгуулдаг. Төсөл нь хамгийн бага тооны туршилтуудыг багтаах болно (дараа нь Женкинст туршиж үзэх зүйл гарах болно). Үйлчилгээний эх кодыг GitHub дээр авах боломжтой: backend и Гарц.

Үйлчилгээ тус бүрийн статусыг шалгахын тулд хаврын идэвхжүүлэгчийг тэдгээрийн хамаарал дээр нэмсэн. Энэ нь /идэвхжүүлэгч/эрүүл мэндийн төгсгөлийн цэгийг үүсгэх бөгөөд үйлчилгээ нь траффик хүлээн авахад бэлэн бол 200 статус, асуудал гарвал 504-ийг буцаана. Энэ тохиолдолд үйлчилгээ нь маш энгийн тул зарим нэг давагдашгүй хүчин зүйл тохиолдсон тохиолдолд хэсэгчлэн ажиллахаас илүү бүрэн боломжгүй болох магадлал өндөр байдаг тул энэ нь зохиомол шалгалт юм. Гэвч бодит системд Actuator нь хэрэглэгчид асуудалтай тулалдаж эхлэхээс өмнө асуудлыг оношлоход тусалдаг. Жишээлбэл, хэрэв мэдээллийн санд хандахад асуудал гарвал бид эвдэрсэн үйлчилгээний тохиолдол бүхий хүсэлтийг боловсруулахыг зогсоосноор автоматаар хариу өгөх боломжтой.

Ар талын үйлчилгээ

Backend үйлчилгээ нь зүгээр л тоолж, хүлээн авсан хүсэлтийн тоог буцаана.

Хянагчийн код:

@RestController
public class RequestsCounterController {

    private final AtomicLong counter = new AtomicLong();

    @GetMapping("/requests")
    public Long getRequestsCount() {
        return counter.incrementAndGet();
    }
}

Хянагч тест:

@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"));
    }
}

Үйлчилгээний гарц

Гарц нь дараах мэдээллээр нэмэлт хүсэлтийг арын үйлчилгээ рүү дамжуулах болно.

  • гарц ID. Энэ нь гарцын нэг тохиолдлыг нөгөөгөөс серверийн хариултаар ялгах боломжтой болгоход шаардлагатай.
  • Маш чухал нууц үгийн үүрэг гүйцэтгэх зарим "нууц" (чухал күүкиний шифрлэлтийн түлхүүрийн тоо)

application.properties доторх тохиргоо:

backend.url=http://localhost:8081
instance.id=${random.int}
secret="default-secret"

Арын адаптер:

@Service
public class BackendAdapter {

    private static final String REQUESTS_ENDPOINT = "/requests";

    private final RestTemplate restTemplate;

    @Value("${backend.url}")
    private String backendUrl;

    public BackendAdapter(RestTemplateBuilder builder) {
        restTemplate = builder.build();
    }

    public String getRequests() {
        ResponseEntity<String> response = restTemplate.getForEntity(
backendUrl + REQUESTS_ENDPOINT, String.class);
        return response.getBody();
    }
}

Хянагч:

@RestController
@RequiredArgsConstructor
public class EndpointController {

    private final BackendAdapter backendAdapter;

    @Value("${instance.id}")
    private int instanceId;

    @Value("${secret}")
    private String secret;

    @GetMapping("/")
    public String getRequestsCount() {
        return String.format("Number of requests %s (gateway %d, secret %s)", backendAdapter.getRequests(), instanceId, secret);
    }
}

Эхлэх:

Бид арын хэсгийг эхлүүлнэ:

./mvnw package -DskipTests
java -Dserver.port=8081 -jar target/microservices-backend-1.0.0.jar

Гарцыг эхлүүлэх:

./mvnw package -DskipTests
java -jar target/microservices-gateway-1.0.0.jar

Бид шалгадаг:

$ curl http://localhost:8080/
Number of requests 1 (gateway 38560358, secret "default-secret")

Бүх зүйл ажиллаж байна. Анхааралтай уншигч бидэнд гарцыг тойрч арын хэсэгт шууд нэвтрэхэд юу ч саад болохгүй гэдгийг анхаарах болно (http://localhost:8081/requests). Үүнийг засахын тулд үйлчилгээг нэг сүлжээнд нэгтгэх ёстой бөгөөд зөвхөн гарц нь гаднаас нь "гацах" ёстой.
Түүнчлэн, хоёр үйлчилгээ хоёулаа нэг файлын системийг хуваалцаж, урсгал үүсгэж, нэг агшинд бие биедээ саад болж эхэлдэг. Манай микро үйлчилгээг тусгаарлах нь сайхан байх болно. Энэ нь өөр өөр машинууд дээр програмуудыг түгээх (маш их мөнгө, хэцүү), виртуал машин (нөөц их шаарддаг, удаан эхлүүлэх) эсвэл контейнержуулалтыг ашиглах замаар хүрч болно. Хүлээгдэж байгаачлан бид гурав дахь сонголтыг сонгох ба Docker савлах хэрэгсэл болгон .

Docker

Товчхондоо, докер нь програм тус бүрээс тусгаарлагдсан контейнер үүсгэдэг. Docker ашиглахын тулд та Dockerfile бичих хэрэгтэй - програмыг бүтээх, ажиллуулах заавар. Дараа нь та зургийг бүтээж, зургийн бүртгэлд байршуулж болно (№. Dockerhub) болон өөрийн бичил үйлчилгээг нэг тушаалаар докержуулсан дурын орчинд байрлуулна.

Докер файл

Зургийн хамгийн чухал шинж чанаруудын нэг бол түүний хэмжээ юм. Авсаархан зураг нь алсын хадгалах газраас хурдан татаж, бага зай эзэлнэ, таны үйлчилгээ хурдан эхлэх болно. Аливаа дүрсийг үндсэн зураг дээр үндэслэн бүтээдэг бөгөөд хамгийн минималист хувилбарыг сонгохыг зөвлөж байна. Сайн сонголт бол Alpine, хамгийн бага багц бүхий бүрэн Linux түгээлт юм.

Эхлээд "духан дээр" Dockerfile бичихийг оролдъё (энэ нь муу арга гэдгийг би шууд хэлье, битгий хий):

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"]

Энд бид төслийг бүтээхдээ аль хэдийн суулгасан JDK бүхий Альпийн нуруунд суурилсан үндсэн зургийг ашиглаж байна. ADD командын тусламжтайгаар бид одоогийн src лавлахыг зурган дээр нэмж, үүнийг ажиллаж байна гэж тэмдэглээд (WORKDIR) бүтээж эхэлнэ. EXPOSE 8080 тушаал нь докерт чингэлэг дэх программ нь 8080 портоо ашиглах болно гэсэн дохио өгдөг (энэ нь програмыг гаднаас нь ашиглах боломжгүй, харин жишээлбэл, нэг докерын сүлжээн дэх өөр контейнерээс програм руу хандах боломжийг олгоно. ).

Үйлчилгээг зураг болгон багцлахын тулд та төсөл бүрийн үндэснээс тушаалуудыг ажиллуулах хэрэгтэй:

docker image build . -t msvc-backend:1.0.0

Үр дүн нь 456 MB хэмжээтэй зураг (үүнээс JDK-ийн үндсэн зураг нь 340 МБ хэмжээтэй) юм. Манай төслийн хичээлийг хуруугаараа тоолж болох ч гэсэн. Манай зургийн хэмжээг багасгахын тулд:

  • Бид олон шатлалт угсралтыг ашигладаг. Эхний шатанд бид төслөө бүтээж, хоёр дахь шатанд JRE суулгаж, гурав дахь шатанд бүгдийг нь шинэ цэвэр Альпийн зураг болгон хуулна. Нийтдээ эцсийн зураг дээр зөвхөн шаардлагатай бүрэлдэхүүн хэсгүүд байх болно.
  • java-н модульчлалыг ашиглая. Java 9-ээс эхлэн та jlink хэрэглүүрийг ашиглан өөрт хэрэгтэй модулиудаас JRE үүсгэх боломжтой

Сонирхолтой хүмүүст зориулж зураг багасгах аргуудын талаар сайн нийтлэл байна. https://habr.com/ru/company/ruvds/blog/485650/.

Эцсийн Docker файл:

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"]

Бид зургийг дахин бүтээж, үүний үр дүнд жингээсээ 6 дахин буурч, 77 МБ болсон. Муугүй шүү. Үүний дараа бэлэн зургуудыг зургийн бүртгэлд байршуулах боломжтой бөгөөд ингэснээр таны зургийг интернетээс татаж авах боломжтой болно.

Docker дээр хамтран ажилладаг үйлчилгээ

Эхлэхийн тулд манай үйлчилгээнүүд нэг сүлжээнд байх ёстой. Докер дээр хэд хэдэн төрлийн сүлжээ байдаг бөгөөд бид тэдгээрийн хамгийн анхдагч нь болох bridge-ийг ашигладаг бөгөөд энэ нь танд нэг хост дээр ажилладаг контейнеруудыг сүлжээнд холбох боломжийг олгодог. Дараах тушаалаар сүлжээ үүсгэнэ үү.

docker network create msvc-network

Дараа нь microservices-backend:1.0.0 зургаар 'backend' нэртэй backend контейнерийг эхлүүлнэ үү:

docker run -dit --name backend --network msvc-net microservices-backend:1.0.0

Гүүрний сүлжээ нь чингэлэгийг нэрээр нь нээх үйлчилгээ үзүүлдэг гэдгийг тэмдэглэх нь зүйтэй. Өөрөөр хэлбэл, арын үйлчилгээ нь докерын сүлжээ дотор байх болно http://backend:8080.

Гарцыг эхлүүлэх:

docker run -dit -p 80:8080 --env secret=my-real-secret --env BACKEND_URL=http://backend:8080/ --name gateway --network msvc-net microservices-gateway:1.0.0

Энэ тушаалд бид хостын 80-р портыг контейнерын 8080-р порт руу дамжуулж байгааг харуулж байна. Бид env тохируулгуудыг ашиглан хавар автоматаар уншигдах орчны хувьсагчдыг тохируулах ба application.properties-ийн шинж чанаруудыг хүчингүй болгоход ашигладаг.

Эхлэсний дараа бид залгана http://localhost/ мөн өмнөх тохиолдлын адил бүх зүйл ажиллаж байгаа эсэхийг шалгаарай.

дүгнэлт

Үүний үр дүнд бид хоёр энгийн микро үйлчилгээг бүтээж, тэдгээрийг докерын саванд хийж, нэг машин дээр хамт ажиллуулсан. Гэсэн хэдий ч үүссэн систем нь хэд хэдэн сул талуудтай:

  • Алдааг тэсвэрлэх чадвар муу - бүх зүйл бидний хувьд нэг сервер дээр ажилладаг
  • Өргөтгөх чадвар муу - ачаалал ихсэх үед нэмэлт үйлчилгээний тохиолдлуудыг автоматаар байрлуулж, тэдгээрийн хоорондох ачааллыг тэнцвэржүүлэх нь сайхан байх болно.
  • Эхлүүлэх нарийн төвөгтэй байдал - бид дор хаяж 3 тушаал оруулах шаардлагатай байсан бөгөөд тодорхой параметрүүдтэй (энэ нь зөвхөн 2 үйлчилгээнд зориулагдсан)

Дээрх асуудлуудыг засахын тулд Docker Swarm, Nomad, Kubernetes эсвэл OpenShift зэрэг хэд хэдэн шийдлүүд байдаг. Хэрэв систем бүхэлдээ Java хэл дээр бичигдсэн бол та Spring Cloud руу харж болно (сайн нийтлэл).

В дараагийн хэсэг Би Kubernetes-ийг хэрхэн тохируулж, төслийг Google Kubernetes Engine дээр байршуулсан тухай ярих болно.

Эх сурвалж: www.habr.com

сэтгэгдэл нэмэх