Lernen, Microservices bereitzustellen. Teil 1. Spring Boot und Docker


Hallo Habr.


In diesem Artikel möchte ich über meine Erfahrungen bei der Schaffung einer Lernumgebung für Experimente mit Microservices sprechen. Beim Studium jedes neuen Werkzeugs wollte ich es immer nicht nur auf dem lokalen Computer ausprobieren, sondern auch unter realistischeren Bedingungen. Aus diesem Grund habe ich beschlossen, eine vereinfachte Microservice-Anwendung zu erstellen, die anschließend mit allen möglichen interessanten Technologien "gewichtet" werden kann. Die Hauptanforderung für das Projekt ist die maximale funktionale Nähe zum realen System.


Anfangs habe ich die Erstellung des Projekts in mehrere Schritte unterteilt:


  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 )

Um die oben genannten Probleme zu lösen, gibt es eine Reihe von Lösungen, z. B. Docker Swarm, Nomad, Kubernetes oder OpenShift. Wenn das gesamte System in Java geschrieben wird, können Sie in Richtung Spring Cloud schauen (ein guter Artikel ).


Im nächsten Teil werde ich darüber sprechen, wie ich Kubernetes konfiguriert und das Projekt für die Google Kubernetes Engine bereitgestellt habe.

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


All Articles