Есть пресловутый Polly, который реализует несколько паттернов. Среди прочих — CircuitBreaker.
Но вот как лучше делать повторы на практике? Можно ли придумать некое универсальное настраиваемое решение? Что используете вы?
Некоторые мысли в форме потока сознания:
Скрытый текст
Давайте так — некая операция, которая не прошла. Тут сразу разделить на устраняемые и не устраняемые без перекомпиляции ошибки:
1. Устраняемые: сетевые (отвалилась база данных, отвалился внешний сервис), системные (как то файл заблокирован для записи, может потом разблокируется, т.к. админ просто открыл его в блокноте и потом закроет или нехватка места на диске — админ почистит).
2. Не устраняемые: ошибка в коде, как то не учли что логин может быть не только email-ом, но и телефоном — и пытаетесь телефон преобразовать к email — можно делать это бесконечное количество раз и результат будет всегда одним и тем же — долбежка не имеет смысла.
Т.е. сразу нужно как-то разделять исключения на два типа. Иногда это не так просто как кажется, иногда нет возможности строгой классификации
Далее. Пусть мы разделили худо-бедно ошибки и можем повторять. Но как часто повторять? Бесконечно? Может таки не стоит — может всему есть предел? Ок, этот предел можно конфигурировать. Но нужна какая-то хитрая формула.
Но вот, допустим, некий сервис внешний был не доступен сутки. Представьте какого значения достигло ЧФ и как долго ждать повтора Вроде можно ограничить — не более чем час. Или же какой-то рычаг оставить — повторить все. К примеру, когда вы узнали что была проблема с базой и она решилась.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, sqrt, Вы писали:
S>>Что такое Polly и CircuitBreaker?
S>https://makolyte.com/csharp-circuit-breaker-with-polly/
S>>> Но вот как лучше делать повторы на практике? S>>Универсальных решений не бывает. Это анти-паттерн.
S>Что мешает сделать универсальное решение? Как вы предлагаете решать?
Здравствуйте, Shmj, Вы писали:
S>Но вот, допустим, некий сервис внешний был не доступен сутки. Представьте какого значения достигло ЧФ и как долго ждать повтора Вроде можно ограничить — не более чем час. Или же какой-то рычаг оставить — повторить все. К примеру, когда вы узнали что была проблема с базой и она решилась.
В отрыве от предметной области разговор бессмысленный. Если у тебя HFT, то ретрай даже в секунду никому не нужен. Если интерактивное приложение (некритичное) — то без привлечения внимания пользователя можно десяток-другой секунд потупить. Если бэкграунд сервис, опять же некритичный, то можно часами ждать. Система типа dead hand должна пытаться вечно.
Здравствуйте, ltc, Вы писали:
ltc>Если интерактивное приложение (некритичное) — то без привлечения внимания пользователя можно десяток-другой секунд потупить. Если бэкграунд сервис, опять же некритичный, то можно часами ждать. Система типа dead hand должна пытаться вечно.
Немного проанализируйте и вы поймете — все эти случаи отличаются только одним параметром — время попыток повтора. Думайте что мешает сделать универсальное решение, где повторы применимы.
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, ltc, Вы писали:
ltc>>Если интерактивное приложение (некритичное) — то без привлечения внимания пользователя можно десяток-другой секунд потупить. Если бэкграунд сервис, опять же некритичный, то можно часами ждать. Система типа dead hand должна пытаться вечно.
S>Немного проанализируйте и вы поймете — все эти случаи отличаются только одним параметром — время попыток повтора. Думайте что мешает сделать универсальное решение, где повторы применимы.
Термин взят из электротехники, где есть предохранитель с повторным включением, т.к. на линиях бывают случайные самопроходящие замыкания. Так и здесь: существуют случайные самопроходящие(сервис подвис на время) так и быстро устранимые сбои. Вот из среднего времени самопрохождения сбоя(максимального, минимального) и нужно исходить.
Здравствуйте, vsb, Вы писали:
vsb>Недавно реализовывал. Первоначальная задержка 5-7 минут. Максимальная 20-28 часов. Увеличивается на 0-40% каждый раз.
Это вы описали параметры конфигурации. Понимаете ли, что параметры можно менять от проекта к проекту — а само решение можно везде использовать одно и то же.
У меня сейчас схожая проблема проблема: есть библиотечный код, который пытается найти файл по текстовому запросу от юзер кода, в случае если ничего подходящего не нашлось я сообщаю об этом юзер коду и ожидаю что он передаст мне новую строку для поиска файла, который опять же может не найтись. Вот сколько раз спрашивать юзер код? Так можно до бесконечности висеть на этом месте.
Я даю юзер коду 10 попыток, после чего делаю некие действия по умолчанию и всё.
Здравствуйте, Shmj, Вы писали:
vsb>>Недавно реализовывал. Первоначальная задержка 5-7 минут. Максимальная 20-28 часов. Увеличивается на 0-40% каждый раз.
S>Это вы описали параметры конфигурации. Понимаете ли, что параметры можно менять от проекта к проекту — а само решение можно везде использовать одно и то же.
В спринге это есть. Я правда не пользовался сам, но вообще — есть. В Golang тоже, недавно к AWS SDK читал, там идет параметр Retry как интерфейс, я так понимаю, как раз чтобы настраивать его можно было.
Здравствуйте, Shmj, Вы писали:
S>Но вот как лучше делать повторы на практике? Можно ли придумать некое универсальное настраиваемое решение? Что используете вы?
Наверное самое универсальное и наиболее используемая модель это делать несколько повторов с экспонтенциальным ростом времени задержки между попытками. Если хотите еще больше "универсальности", то к времени задержки можно добавить случайную величину в пределах 1/4 этого времени. Так делают чтобы сделать нагрузку на ресурс более равномерной после провала в его доступности когда есть много клиентов, которые в противном случае могут параллельно пытаться делать повторы в одни и те же моменты времени создавая этим ненужный аврал.
Здравствуйте, Aquilaware, Вы писали:
A>Наверное самое универсальное и наиболее используемая модель это делать несколько повторов с экспонтенциальным ростом времени задержки между попытками. Если хотите еще больше "универсальности", то к времени задержки можно добавить случайную величину в пределах 1/4 этого времени. Так делают чтобы сделать нагрузку на ресурс более равномерной после провала в его доступности когда есть много клиентов, которые в противном случае могут параллельно пытаться делать повторы в одни и те же моменты времени создавая этим ненужный аврал.
Вот мне, кстати, всегда было непонятно, почему нужно именно экспоненциальное время задержки. Почему не арктангенс или кусочно-линейное? Ну, типа попробовали ежеминутно-через 5 минут — через полчаса — через час — и долбим раз в час.
Тогда у нас матожидание бездарно потерянного времени после починки системы ограничено получасом. А не неизвестным заранее значением — когда в итоге после починки сервера нужно ещё и идти перезапускать клиента, который "следующая попытка подключения будет произведена через 32 дня".
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Тогда у нас матожидание бездарно потерянного времени после починки системы ограничено получасом. А не неизвестным заранее значением — когда в итоге после починки сервера нужно ещё и идти перезапускать клиента, который "следующая попытка подключения будет произведена через 32 дня".
Супер! Столкнулся с такой проблемой на практике. Внешний сервис упал на 24 часа. Редко, но бывает.
Однако же — долбить раз в час на протяжении 1 года каждый час = тоже глупо. По-моему должен быть какой то лимит. Ну ок, бывает что нечто упадет на сутки. Ну на трое суток в худшем случае. Но зачем долбить после 3 суток или на крайняк 5 дней?
По сути тут дело все в конфигурации. Нужно 3 параметра:
1. На короткой дистанции. Может просто сетевая ошибка рядовая. Тут можно по тем же числам Фибоначчи или тем же экспоненциальным ростом.
2. Предел, после которого значение переходит в константу. К примеру, 1 час. Раз в час это уже достаточно редко и уже не будет так уж нагружать сервер.
3. Все-таки предел, когда даже долбежку раз в час нужно признать бессмысленной. К примеру, спустя 3 суток.
S>Немного проанализируйте и вы поймете — все эти случаи отличаются только одним параметром — время попыток повтора. Думайте что мешает сделать универсальное решение, где повторы применимы.
универсализм — как правило несет избыточность, зачем мне нужно решение с хиулиардом параметров если в моем случае я использую только 1
Здравствуйте, Shmj, Вы писали:
S>Однако же — долбить раз в час на протяжении 1 года каждый час = тоже глупо.
Почему? Нужно какое-то математическое обоснование термина "глупо". С моей точки зрения, лишнее обращение к серверу плохо только создаваемой нагрузкой. Если мы долбим ежечасно в течение года, то это всего-то 8760 обращений.
Сколько обращений к этому сервису мы делаем обычно? Несколько раз в минуту? Ну ок, при неисправности мы снижаем нагрузку на 2 порядка. Можно и на 3 — ну, то есть должно быть какое-то соотношение между "обычной" и "аварийной" интенсивностью.
S>По-моему должен быть какой то лимит. Ну ок, бывает что нечто упадет на сутки. Ну на трое суток в худшем случае. Но зачем долбить после 3 суток или на крайняк 5 дней?
Потому что ремонт может занять и 3 суток, и 5 дней.
Но опять же, всё зависит от контекста. Если для нас это жизненно важный сервис, то вместе с ним лежим и мы. Допустим, он сломался навсегда — владельцы разорились, не смогли восстановить. Или вообще, мы понимаем, что нет смысла полагаться на сервис, SLA которого настолько плоха. За какое время мы переключимся на альтернативу? Если за неделю, то не имеет никакого смысла долбить больше недели — имеет смысл ввести регламент "сервис, не отвечающий более суток, подлежит замене". С таким регламентом через 8 дней от начала сбоя у нас будет новая версия кода, в которой обращений к этому сервису вовсе нет.
А долбление раз в час нужно только для того, чтобы если этот сервис через пару дней всё же поднялся, то мы продолжим работу на нём, пока инженеры пилят замену.
S>По сути тут дело все в конфигурации. Нужно 3 параметра:
S>1. На короткой дистанции. Может просто сетевая ошибка рядовая. Тут можно по тем же числам Фибоначчи или тем же экспоненциальным ростом. S>2. Предел, после которого значение переходит в константу. К примеру, 1 час. Раз в час это уже достаточно редко и уже не будет так уж нагружать сервер. S>3. Все-таки предел, когда даже долбежку раз в час нужно признать бессмысленной. К примеру, спустя 3 суток.
Да, согласен, похоже на правду.
Но, повторюсь, я сам правильного ответа не знаю. Наверняка есть какие-то учебники по SRE, где всё это расписано и дано в упражнениях.
Возможно, правильный профиль backoff зависит от распределения времени восстановления после сбоя с учётом распределения вероятностей различных типов сбоев.
И вот эта вот экспоненциальная формула тщательно выведена и обоснована для некоторого класса таких распределений
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>>Однако же — долбить раз в час на протяжении 1 года каждый час = тоже глупо. S>Почему? Нужно какое-то математическое обоснование термина "глупо". С моей точки зрения, лишнее обращение к серверу плохо только создаваемой нагрузкой. Если мы долбим ежечасно в течение года, то это всего-то 8760 обращений. S>Сколько обращений к этому сервису мы делаем обычно? Несколько раз в минуту? Ну ок, при неисправности мы снижаем нагрузку на 2 порядка. Можно и на 3 — ну, то есть должно быть какое-то соотношение между "обычной" и "аварийной" интенсивностью.
Тут, скорее, не мат. обоснование а практическая целесообразность, здравый смысл и лицензионное соглашение.
К примеру, если речь о сервисе пополнения счета. Приняли от вас оплату и пробуем провести через шлюз оператора как его партнеры. Не прошло. Ну ок, платеж в статусе — на обработке. Думаю и ежу понятно, что в таком статусе — ну день еще может повисеть, ну 3 дня с учетом выходных — а вот год ждать пока тебе телефон пополнят — никто не будет..
S>>По-моему должен быть какой то лимит. Ну ок, бывает что нечто упадет на сутки. Ну на трое суток в худшем случае. Но зачем долбить после 3 суток или на крайняк 5 дней? S>Потому что ремонт может занять и 3 суток, и 5 дней.
Если ремонт 5 дней — то нужно отказываться от услуг такого поставщика. И быстренько за 1-2 дня переключиться на другого.
S>А долбление раз в час нужно только для того, чтобы если этот сервис через пару дней всё же поднялся, то мы продолжим работу на нём, пока инженеры пилят замену.