Управление зависимостями гостевых исполняемых файлов — в локальной сервисной сети

#c# #azure-service-fabric #dependency-management #service-fabric-on-premises

#c# #azure-service-fabric #управление зависимостями #локальная сервиснаясеть

Вопрос:

Недавно мы решили начать использовать локальную структуру служб и столкнулись с проблемой «зависимости».

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

Пример, чтобы было понятно:

На приведенной ниже диаграмме служба B зависит от службы A. Если служба A столкнется с непредвиденной ошибкой и будет перезапущена, служба B перейдет в состояние «ошибка» (о котором не будет сообщено в структуру). Это означает, что служба B сообщит о нормальном состоянии работоспособности, хотя она находится в состоянии ошибки.

Мы думали о решении, основанном на этих линиях:

Создайте независимую службу, которая отслеживает события состояния работоспособности всех реплик / разделов / приложений в кластере и содержит все дерево зависимостей.

Когда состояние работоспособности службы изменяется, она перезапускает свои прямые зависимости, что вызовет эффект домино событий -> перезапускается до тех пор, пока не будет сброшено все поддерево (как показано на схеме потока событий-> Действий ниже).

Поток действий события

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

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

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

Комментарии:

1. Когда вы ссылаетесь на «Отчет о работоспособности», вы имеете в виду отчет о состоянии реплики в Service Fabric?

2. @OlegKarasik да, об этом сообщается в отчетах о работоспособности

Ответ №1:

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

  • Ввести повторные попытки для неудачных операций с задержкой между ними. Время между задержками может расти экспоненциально. Это простой вариант для реализации, если в настоящее время вы часто выполняете взаимодействие в стиле удаленного вызова процедур (RPC) между службами. Это может быть очень эффективным, если перезапуск ваших зависимых служб не займет слишком много времени. Polly — хорошо известная библиотека для реализации повторных попыток.

  • Используйте автоматические выключатели для прекращения связи с отказывающими службами. В этой метафоре между двумя службами, нормально взаимодействующими, образуется замкнутый контур. Автоматический выключатель контролирует обмен данными. Если он обнаруживает некоторое количество неудачных соединений, он «размыкает» схему, вызывая немедленный сбой любых дальнейших соединений. Затем автоматический выключатель отправляет периодические запросы отказывающей службе для проверки ее работоспособности и замыкает цепь, как только отказывающая служба начинает функционировать. Это немного сложнее, чем политики повторных попыток, поскольку вы несете ответственность за предотвращение сбоя вашей службы при разомкнутом контуре, а также за принятие решения о том, что представляет собой работоспособную службу. Polly также поддерживает автоматические выключатели

  • Используйте очереди для формирования полностью асинхронной связи между службами. Вместо того, чтобы напрямую обмениваться данными со службой B с A, поставьте исходящие операции в очередь для A в службе B. Обработайте очередь в ее собственном потоке — не допускайте сбоев связи, чтобы избежать обработки очереди. Вы также можете добавить входящую очередь в службу A для получения сообщений из исходящей очереди службы B, чтобы полностью изолировать обработку сообщений от сети. Это, вероятно, самый надежный, но и самый сложный способ, поскольку он требует архитектуры, сильно отличающейся от RPC, и вы также должны решить, как обращаться с сообщениями, которые неоднократно завершаются ошибкой. Вы можете немедленно повторить неудачную попытку отправки сообщений, отправить их в конец очереди после задержки, отправить их в коллекцию «мертвых писем» для ручной обработки или вообще удалить сообщение. Поскольку вы используете гостевые исполняемые файлы, у вас нет возможности пользоваться надежными коллекциями, которые помогли бы в этом процессе, поэтому стороннее решение, такое как RabbitMQ, может оказаться полезным, если вы решите пойти этим путем.

Комментарии:

1. К сожалению, исправление гостевых исполняемых файлов не является вариантом.

2. Насколько велика поверхность API ваших гостевых исполняемых файлов? Не могли бы вы потенциально обернуть их, написав другую службу, которая направляет вызовы в гостевой исполняемый файл? Вы могли бы внедрить туда отказоустойчивость.

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