Как стать автором
Обновить
890.81
OTUS
Цифровые навыки от ведущих экспертов

Масштабирование микросервисов Spring Boot

Время на прочтение4 мин
Количество просмотров3K

Давайте представим, что мы уже написали наше Spring Boot приложение, и оно успешно работает на протяжении некоторого времени. И теперь мы понимаем, что для того, чтобы справиться с возросшей нагрузкой и повысить доступность, нам необходимо запустить несколько новых инстансов сервиса. Но мы не подумали об этом заранее, на этапе разработки.

Так что же может помешать нам просто взять и запустить еще несколько инстансов?

  1. Использование планировщиков.

  2. Использование WebSocket.

  3. Пользовательские сессии, хранящиеся в памяти.

  4. Кэш приложения - это может быть либо простой параллельный hashmap в компонентах, либо spring кэш.

Что ж, все это можно легко адаптировать с помощью соответствующих инструментов.

Планировщики

Использование распределенных планировщиков не самая тривиальная задача, которая, к тому же, требует дополнительное время для настройки и правки кода. Наша цель - как можно быстрее реализовать перехода от 1 до N одновременно работающих инстансов.

К счастью, существует библиотека Shedlock с интеграцией Spring, которая позволяет осуществить наш замысел с помощью всего лишь пары аннотаций.

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

Нам необходимо включить Shedlock с блокировкой по умолчанию на 5 минут (максимум).

@Configuration
@EnableScheduling
@EnableSchedulerLock(defaultLockAtMostFor = "5m")
public class ApplicationConfiguration {
}

И добавить аннотацию ShedLock'а с указанием названия конкретного планировщика.

@Scheduled(cron = "0 0 * * * *")
@SchedulerLock(name = "myTask")
public void run() {
   // do something
}

Таким образом, в следующий цикл планировщика каждый инстанс будет пытаться записать строку о себе в таблицу блокировок, и первый, кто успеет это сделать, продолжит выполнение задачи. Все остальные пропускают цикл.

Блокировка задачи в нашем случае будет висеть максимум 5 минут. По завершении задачи инстанс снимает блокировку в таблице. Если по истечении 5 минут блокировка не была снята, другие инстансы будут считать, что этот инстанс завис во время выполнения задачи.

Websocket

Если пользователи нашего приложения могут отправлять друг другу сообщения и для реализации этой функции мы используем WebSocket, возможна такая ситуация, когда пользователь Вова подключен к инстансу A, а пользователь Алиса подключена к инстансу B. Мы оказываемся в ситуации, когда инстансы должны каким-то образом самостоятельно понимать, куда им отправлять сообщения и обмениваться ими между собой.

Написание такого уровня - это кропотливая работа, которая значительно замедляет масштабирование приложения. Вместо этого мы можем использовать готовую реализацию Spring BrokerRelay, которая использует внешнего брокера (RabbitMQ, ActiveMQ и т. д.) для обработки WebSocket, управления подписками и т. д.

@Configuration
public class WebSocketConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableStompBrokerRelay("/topic", "/queue")
            .setClientLogin("guest")
            .setClientPasscode("guest")
            .setSystemLogin("guest")
            .setSystemPasscode("guest")
            .setRelayHost("127.0.0.1")
            .setRelayPort(61613);
    }
}

В этом случае все сообщения в /topic и /queue будут пересылаться внешнему брокеру.  С детальной схемой взаимодействия можно ознакомиться в документации Spring.

Пользовательские сессии

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

Но для JDBC, достаточно добавить всего одну зависимость.

<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-jdbc</artifactId>
</dependency>

И установить свойство в application.properties:

spring.session.store-type=jdbc

Однако, в данном случае, не стоит забывать, что данные сессии будут храниться в виде блобов, и иногда во время обновления Spring, вам необходимо будет чистить сессии из-за проблем с десериализацией старых объектов.

Кэш приложения

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

Чтобы все инстансы использовали общий кэш, стоит подключить внешнее хранилище, например Redis, Apache Ignite, Hazelcast и т.д.

В случае использования Spring-Cache или Redis достаточно добавить одну зависимость.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

После этого с аннотацией @EnableCaching, Spring Boot автоматически активирует Redis в качестве конфигурации по умолчанию.

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

@Bean
public RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer() {
    return builder -> builder
      .withCacheConfiguration(“AccountCache",
        RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(60)))
      .withCacheConfiguration(“ProductCache",
        RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(120)));
}

Заключение

Таким образом, даже если вы не задумывались о масштабировании при создании приложения, существует набор инструментов, которые помогут сделать возможным переход от 1 к N одновременно запущенных инстансов без переписывания бизнес-логики самого сервиса.


Материал подготовлен нашим экспертом - Александром Коженковым и опубликован в преддверии старта курса «Microservice Architecture».

Всех желающих приглашаем на открытый урок «Паттерны аутентификации и авторизации». На занятии будет рассказано про различные паттерны аутентификации и авторизации. Рассмотрена сессионная аутентификация на основе кук и на основе токенов (jwt), работа identity провайдеров.
>> Регистрация

Теги:
Хабы:
Всего голосов 9: ↑7 и ↓2+5
Комментарии3

Публикации

Информация

Сайт
otus.ru
Дата регистрации
Дата основания
Численность
101–200 человек
Местоположение
Россия
Представитель
OTUS