Apprendre à déployer des microservices. Partie 1. Spring Boot et Docker


Bonjour, Habr.


Dans cet article, je veux parler de mon expĂ©rience dans la crĂ©ation d'un environnement d'apprentissage pour des expĂ©riences avec des microservices. Lors de l'Ă©tude de chaque nouvel outil, j'ai toujours voulu l'essayer non seulement sur la machine locale, mais aussi dans des conditions plus rĂ©alistes. Par consĂ©quent, j'ai dĂ©cidĂ© de crĂ©er une application de microservice simplifiĂ©e, qui peut ensuite ĂȘtre "pondĂ©rĂ©e" avec toutes sortes de technologies intĂ©ressantes. La principale exigence du projet est sa proximitĂ© fonctionnelle maximale avec le systĂšme rĂ©el.


Au départ, j'ai divisé la création du projet en plusieurs étapes:


  1. — '' (backend) '' (gateway), docker-


    : Java 11, Spring Boot, Docker, image optimization


  2. Kubernetes Google Kubernetes Engine


    : Kubernetes, GKE, resource management, autoscaling, secrets


  3. Helm 3


    : Helm 3, chart deployment


  4. Jenkins


    : Jenkins configuration, plugins, separate configs repository



.


, , . , , 20% (, , 80% ). , , , . .



Java 11 Spring Boot. REST. ( , Jenkins). GitHub: .


, Spring Actuator. /actuator/health 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"));
    }
}

Gateway

, :


  • 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


, , . , Dockerfile — . , (№ DockerHub) .


Dockerfile


— . , , . , . 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"]

Alpine JDK . ADD src, (WORKDIR) . EXPOSE 8080 , 8080 ( , , , ).


:


docker image build . -t msvc-backend:1.0.0

456 ( JDK 340 ). , . :


  • . , JRE, Alpine . .
  • java. Java 9, jlink JRE

, https://habr.com/ru/company/ruvds/blog/485650/.


Dockerfile:


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 anshelen@yandex.ru"
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

'backend' microservices-backend:1.0.0:


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

, bridge- service discovery . 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 )

Pour résoudre les problÚmes ci-dessus, il existe un certain nombre de solutions, telles que Docker Swarm, Nomad, Kubernetes ou OpenShift. Si l'ensemble du systÚme sera écrit en Java, vous pouvez regarder vers Spring Cloud (un bon article ).


Dans la partie suivante, je parlerai de la façon dont j'ai configuré Kubernetes et déployé le projet sur Google Kubernetes Engine.

Source: https://habr.com/ru/post/undefined/


All Articles