Учимся Ρ€Π°Π·Π²ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ микросСрвисы. Π§Π°ΡΡ‚ΡŒ 1. Spring Boot ΠΈ Docker

Учимся Ρ€Π°Π·Π²ΠΎΡ€Π°Ρ‡ΠΈΠ²Π°Ρ‚ΡŒ микросСрвисы. Π§Π°ΡΡ‚ΡŒ 1. Spring Boot ΠΈ Docker

ΠŸΡ€ΠΈΠ²Π΅Ρ‚, Π₯Π°Π±Ρ€.

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ я Ρ…ΠΎΡ‡Ρƒ Ρ€Π°ΡΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎ своСм ΠΎΠΏΡ‹Ρ‚Π΅ создания ΡƒΡ‡Π΅Π±Π½ΠΎΠΉ срСды для экспСримСнтов с микросСрвисами. ΠŸΡ€ΠΈ ΠΈΠ·ΡƒΡ‡Π΅Π½ΠΈΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ инструмСнта ΠΌΠ½Π΅ всСгда Ρ…ΠΎΡ‚Π΅Π»ΠΎΡΡŒ Π΅Π³ΠΎ ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π° локальной машинС, Π½ΠΎ ΠΈ Π² Π±ΠΎΠ»Π΅Π΅ рСалистичных условиях. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ я Ρ€Π΅ΡˆΠΈΠ» ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΡƒΠΏΡ€ΠΎΡ‰Π΅Π½Π½ΠΎΠ΅ микросСрвисноС ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ впослСдствии ΠΌΠΎΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ "ΠΎΠ±Π²Π΅ΡˆΠΈΠ²Π°Ρ‚ΡŒ" всякими интСрСсными тСхнологиями. ОсновноС Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΊ ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Ρƒ β€” Π΅Π³ΠΎ максимальная Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½Π°Ρ ΠΏΡ€ΠΈΠ±Π»ΠΈΠΆΠ΅Π½Π½ΠΎΡΡ‚ΡŒ ΠΊ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ систСмС.

Π˜Π·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ я Ρ€Π°Π·Π±ΠΈΠ» созданиС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π° Π½Π° нСсколько шагов:

  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 [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

Π”Π°Π»Π΅Π΅ запустим ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Π±Π΅ΠΊΠ΅Π½Π΄Π° с ΠΈΠΌΠ΅Π½Π΅ΠΌ ‘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 сСрвисов)

Для устранСния Π²Ρ‹ΡˆΠ΅ΠΏΠ΅Ρ€Π΅Ρ‡ΠΈΡΠ»Π΅Π½Π½Ρ‹Ρ… ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌ сущСствуСт ряд Ρ€Π΅ΡˆΠ΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ Docker Swarm, Nomad, Kubernetes ΠΈΠ»ΠΈ OpenShift. Если вся систСма Π±ΡƒΠ΄Π΅Ρ‚ написана Π½Π° Java ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΡΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Π² сторону Spring Cloud (Ρ…ΠΎΡ€ΠΎΡˆΠ°Ρ ΡΡ‚Π°Ρ‚ΡŒΡ).

Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ части я расскаТу ΠΏΡ€ΠΎ Ρ‚ΠΎ, ΠΊΠ°ΠΊ я настраивал Kubernetes ΠΈ Π΄Π΅ΠΏΠ»ΠΎΠΈΠ» ΠΏΡ€ΠΎΠ΅ΠΊΡ‚ Π² Google Kubernetes Engine.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ: habr.com