JavaRush /Курсы /Модуль 5. Spring /Лекция 163: Преимущества микросервисов: масштабируемость,...

Лекция 163: Преимущества микросервисов: масштабируемость, отказоустойчивость, независимость команд

Модуль 5. Spring
17 уровень , 2 лекция
Открыта

Сегодня мы поговорим о трёх ключевых преимуществах микросервисов: масштабируемости, отказоустойчивости и независимости команд. Эти три кита микросервисов — первопричина того, что многие крупные компании (такие, как Netflix и Amazon) переходят на микросервисные архитектуры.


Масштабируемость: масштабируем всё на свете!

Масштабируемость — это способность вашей системы "расти" (либо по числу пользователей, либо по нагрузке), сохраняя свою производительность.

Допустим, у вас есть магазин мороженого. В жаркие дни очередь увеличивается, и вы добавляете еще одну кассу (или, если вы программист, сервер). В микросервисной архитектуре каждая касса (или служба) может масштабироваться независимо от других.

Горизонтальное масштабирование

Микросервисы позволяют масштабировать только те части системы, которые реально требуют увеличения ресурсов.

Например, у вас есть сервис логирования и сервис обработки заказов. При этом ваш сервис логирования справляется отлично. Значит, просто оставьте его в покое. А вот сервис обработки заказов буквально загибается под огромным количеством запросов. Что ж, поднимите несколько дополнительных инстансов только для него.

Пример:


// Сервис "Обработка заказов"
@RestController
@RequestMapping("/orders")
public class OrderService {

    @GetMapping("/{id}")
    public Order getOrder(@PathVariable String id) {
        // Логика для получения заказа из базы данных
        return orderRepository.findById(id);
    }
}

Подумайте: если нагрузка на этот "OrderService" растёт, мы можем просто поднять больше таких инстансов и сбалансировать нагрузку через, скажем, Nginx или Kubernetes.

Гибкость выбора технологий

В микросервисах вы можете выбрать другой язык программирования или технологию для внедрения конкретного сервиса. Например, для вычислений ML используйте Python, а для обрабатывающего REST API — Java.

Отказоустойчивость: у вас не упадёт всё сразу

Представьте себе ситуацию, когда у вас падает монолитное приложение, а вместе с ним "умирает" и весь функционал. Пользователи злятся, уходят, и ваш проект на грани гибели. В микросервисах же сбой одного сервиса не убивает всю систему.

Как микросервисы обеспечивают отказоустойчивость? Каждый микросервис можно изолировать, чтобы сбой в одном сервисе минимально сказывался на других. Давайте представим, что у нас есть три сервиса:

  • OrderService (обработка заказов)
  • PaymentService (обработка платежей)
  • NotificationService (уведомления клиентов)

Если NotificationService упадёт, пользователи всё равно могут делать заказы и оплачивать их. Конечно, они не получат SMS-оповещение, но основной функционал сохранится.


Пример кода с изоляцией сбоев


// Пример Circuit Breaker для отказоустойчивости с помощью Resilience4j
@Retry(name = "default", fallbackMethod = "fallbackResponse")
public String processOrder(String order) {
    // Основной логика выполнения
    return orderService.process(order);
}

public String fallbackResponse(String order, Throwable t) {
    return "Service is temporarily unavailable. Please try again later.";
}

Здесь, если OrderService будет перегружен, ваше приложение может вернуть fallback-ответ, вместо того чтобы зависнуть.

События деградации функционала (Fallback)

Микросервисы часто используют концепцию деградации. Это означает, что в случае сбоя одного сервиса, другой может взять на себя часть работы или дать "неидеальный", но рабочий ответ.

Пример из жизни: Google Maps. Если у вас пропал доступ к интернету, Google Maps всё равно показывает предыдущие загруженные карты. Это пример деградации функционала.

Отказоустойчивость в деле: реальный пример

Uber использует микросервисы для обеспечения бесперебойной работы даже при сбоях. Если сервер маршрутизации (определяющий кратчайший путь) выходит из строя, пользователь всё равно может вызвать машину — просто маршрут будет рассчитан немного позже.


Независимость команд: меньше головной боли для всех

Когда вы работаете в большой компании, разработкой одного приложения могут заниматься десятки, а то и сотни инженеров. Разработка монолита в этой ситуации превращается в кошмар. Если команда А поменяет один метод, команда Б может внезапно обнаружить сотни ошибок в своей части кода.

Каждая команда работает над своим сервисом, который независим от других. Это снижает количество конфликтов и улучшает производительность.


Пример: Независимость через API


// Команда А: разрабатывает "UsersService"
@RestController
@RequestMapping("/users")
public class UsersService {
    @GetMapping("/{id}")
    public User getUser(@PathVariable String id) {
        return userRepository.findById(id);
    }
}


// Команда Б: разрабатывает "OrdersService"
@RestController
@RequestMapping("/orders")
public class OrdersService {
    @GetMapping("/user/{userId}")
    public List<Order> getUserOrders(@PathVariable String userId) {
        return orderRepository.findByUserId(userId);
    }
}

Здесь "OrdersService" знает только про API "UsersService", а не его внутреннюю реализацию. Изменения внутри "UsersService" не сломают "OrdersService", если API остаётся неизменным.


Подход к программированию влияет на подходы в организации

Интересный факт: микросервисы не только меняют архитектуру, но и модифицируют организационную структуру в компании. Эта идея даже имеет название — "Закон Конуэя" (Melvin Conway): структура вашей системы будет повторять структуру вашей организации.

Хотите независимые микросервисы? Дайте вашим командам независимость!

Независимость в деле: пример Amazon

Amazon, как и Google, разбил свои команды на небольшие автономные группы, каждая из которых работает над своим микросервисом. Эти команды называются "двухпиццевые" команды (two-pizza teams), потому что команда должна быть такой маленькой, чтобы её можно было накормить двумя пиццами.


Резюме

Микросервисная архитектура приобрела популярность благодаря нескольким ключевым преимуществам: возможности масштабировать отдельные компоненты системы, обеспечению отказоустойчивости при сбоях и поддержке автономной работы команд разработчиков. Это мощный подход, который одновременно требует основательного понимания и тщательной реализации.

Важно помнить, что гибкость микросервисной архитектуры требует ответственного подхода, особенно в вопросах мониторинга и поддержки. Без должного контроля за работой сервисов невозможно обеспечить надежность системы в целом.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ