
مرحبا يا هابر.
في هذه المقالة ، أود أن أتحدث عن تجربتي في إنشاء بيئة تعليمية للتجارب مع الخدمات الصغيرة. عند دراسة كل أداة جديدة ، أردت دائمًا تجربتها ليس فقط على الجهاز المحلي ، ولكن أيضًا في ظروف أكثر واقعية. لذلك ، قررت إنشاء تطبيق خدمة مصغر مبسط ، يمكن بعد ذلك "وزنه" مع جميع أنواع التقنيات المثيرة للاهتمام. الشرط الرئيسي للمشروع هو قربه الوظيفي الأقصى من النظام الحقيقي.
في البداية ، قمت بتقسيم إنشاء المشروع إلى عدة خطوات:
— '' (backend) '' (gateway), docker-
: Java 11, Spring Boot, Docker, image optimization
Kubernetes Google Kubernetes Engine
: Kubernetes, GKE, resource management, autoscaling, secrets
Helm 3
: Helm 3, chart deployment
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
, :
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/ , , .
, - . , , :
لحل المشاكل المذكورة أعلاه ، هناك عدد من الحلول ، مثل Docker Swarm أو Nomad أو Kubernetes أو OpenShift. إذا تمت كتابة النظام بالكامل بلغة Java ، فيمكنك التطلع إلى Spring Cloud ( مقالة جيدة ).
في الجزء التالي ، سأتحدث عن كيفية تكوين Kubernetes ونشر المشروع على Google Kubernetes Engine.