
Стежок, сделанный вовремя, стоит девяти
Пандемия Covid-19 заставила многие страны ввести карантин в попытке сдержать болезнь. Только основные услуги были открыты для доступа общественности. Большинству из нас приходилось оставаться дома неделями и месяцами.
Это нарушило нормальную жизнь сильнее, чем когда-либо. Но почему правительства пошли на такой радикальный шаг?

Эта мера была неизбежна для предотвращения крупномасштабных вспышек, которые в противном случае были бы разрушительными. В конце концов, блокировку снимали поэтапно, по мере снижения числа случаев заражения коронавирусом.
Весь сценарий представляет собой реальную аналогию автоматического выключателя.
Концепция автоматических выключателей изначально пришла из электроники. Если посмотреть Википедию, то он определяется как автоматический выключатель для защиты цепи от повреждений, вызванных перегрузкой по току или коротким замыканием. Это автоматическое средство отключения питания от неисправной системы.
Как только неисправность устранена, переключатель замыкается, чтобы восстановить питание прерванной цепи.
Итак, как это применимо к нам?
Зачем нам нужен прерыватель цепи в наших микросервисах?
Посмотрим правде в глаза, все службы могут дать сбой или дать сбой в какой-то момент времени. Сети могут стать ненадежными, системам может не хватать ресурсов, базы данных могут выйти из строя, глобальные глобальные сборщики могут зайти в тупик, а центр обработки данных могут атаковать зомби. Ладно, может не последний 😁. Но вы поняли!
Нам нужно обеспечить отказоустойчивость наших сервисов, чтобы изящно справляться с такими ситуациями.
Рассмотрим этот пример.

С сервера API мы вызываем службу рекомендаций фильмов, чтобы дать рекомендации пользователям фильмов. Предположим, что БД фильмов по какой-то причине работает медленно, и, следовательно, служба рекомендаций фильмов также работает медленно. Что произойдет, если мы продолжим отправлять запросы с сервера API? Это усилит давление на Db и может еще больше ухудшить ситуацию.
Кроме того, потоки службы рекомендаций фильмов будут заняты обработкой запросов с большим количеством ответов, что приведет к уменьшению количества свободных потоков для обработки других запросов, что в конечном итоге приведет к отключению службы.
Вместо того, чтобы продолжать отправлять запросы и перегружать службу рекомендаций фильмов, мы можем выбрать более разумный маршрут. Сервер API может сказать службе рекомендаций: «Эй, почему бы тебе не сделать перерыв? Отдохните и оправьтесь от любых проблем, которые у вас есть. Я свяжусь с вами через некоторое время».
Мы можем дать API-серверу переключатель, чтобы отключить и прекратить все связи со службой рекомендаций фильмов на некоторое время.
Что будет делать сервер API с запросами, которые должны быть отправлены в рекомендательный сервис? Ну, у него есть 2 варианта. Если неисправная служба является критической службой, она может быстро выйти из строя и показать пользователям сообщение об ошибке. Если сервис некритичен, то мы можем обойти его и предоставить пользователям немного ухудшенный опыт.
После этого мы можем повторить несколько запросов, чтобы проверить, не работает ли неисправный сервис или работает медленно.
Вот видео, показывающее, как Hotstar делает изящную деградацию, обходя некритические сервисы, когда возникает непредвиденная ошибка.
Если мы реализуем это решение самостоятельно, оно будет навязчивым для кодовой базы и добавит значительных накладных расходов. Здесь нам может помочь автоматический выключатель.
То, что вы хотите, чтобы автоматические выключатели делали, это:
- Следите за ошибками обслуживания в режиме реального времени. Ищите чрезмерные ошибки, неоправданно медленное время отклика и т. д.
- Выключите и прервите этот поток, чтобы предотвратить перегрузку остальной системы.
- Периодически проверяйте, восстановилась ли неисправная служба.
Реализация автоматического выключателя в весенней загрузке с помощью Resiliency4j
Hysterix, Resiliency4j и Sentinel — одни из самых популярных библиотек автоматических выключателей. Hysterix в настоящее время устарел и находится в режиме обслуживания. По сравнению с Sentinel, Resilience4j очень легкий и имеет более детализированные элементы управления. В этой демонстрации мы будем использовать Resilience4j.
В нашей демонстрации будет использоваться служба панели управления фильмами на основе весенней загрузки, которая рекомендует фильмы пользователям. Служба панели взаимодействует со службой рекомендаций фильмов через сервер Eureka.

Во-первых, давайте настроим службу рекомендаций фильмов, которая возвращает рекомендуемые фильмы для пользователя.
Теперь мы настроим службу панели мониторинга фильмов, которая будет интерфейсом к службе рекомендаций фильмов.
Полный код можно найти здесь.
Теперь запустите службы и сервер eureka. Теперь мы можем получить доступ к конечной точке /dashboard на нашем сервисном порту панели управления фильмами и просмотреть наш список рекомендаций фильмов.

Наши услуги готовы. Наденьте рабочие ботинки и приготовьтесь к автоматическому выключателю!
Во-первых, нам нужно добавить реактивную версию автоматического выключателя Resilience4j в качестве зависимости.
Когда у нас есть автоматический выключатель, все, что нам нужно сделать, это позвонить run. Run принимает Mono или Flux и необязательную функцию. Необязательный параметр Function действует как запасной вариант, если что-то пойдет не так с исходным запросом. В нашем примере мы вернемся к getDefaultMovies().
Вот и все. Наш автоматический выключатель готов.
Теперь давайте отключим сервис рекомендаций фильмов. Исходного сервиса больше нет, но благодаря Resilience4J мы можем вернуться к фильмам по умолчанию и сделать наших пользователей счастливыми.

Конфигурации Resiliency4j
Resiliency4j предоставляет множество детальных конфигураций для изменения поведения автоматического выключателя по умолчанию.
- Вы можете выбирать между скользящим окном на основе подсчета и скользящим окном на основе времени. Например, мы можем настроить автоматический выключатель на основе подсчета, чтобы он «размыкал цепь», если 70% из последних 25 вызовов не удалось. Точно так же мы могли бы приказать автоматическому выключателю на основе времени разомкнуть цепь, если 80 % вызовов за последние 30 секунд были неудачными.
- Вы можете настроить порог частоты отказов, выше которого автоматический выключатель переходит в размыкание и начинает замыкать вызовы.
- Вы можете настроить порог продолжительности, выше которого вызовы считаются медленными, и увеличить количество медленных вызовов.
- Вы можете определить список исключений, которые должны считаться сбоем.
Полный список конфигураций ищите здесь.
Прощальные мысли
Я надеюсь, что эта статья смогла прояснить, почему автоматические выключатели важны для создания отказоустойчивых систем и как их реализовать.
Автоматические выключатели — это только одна часть головоломки для обеспечения отказоустойчивости вашей системы. Кроме того, Resiliency4J предоставляет несколько других механизмов отказоустойчивости, таких как переборки, ограничители скорости, повторные попытки и ограничения по времени. Но это тема для другого блога!