Обработка исключений в программе, которая должна работать 24/7

14

Я читал, что мы должны ловить только те исключения, которые могут быть обработаны, что делает отлов базового класса исключений (в данном случае C #) плохой идеей (помимо других причин). В настоящее время я являюсь частью проекта, в котором до сих пор мне не удалось увидеть ничего, кроме базового исключения. Я упомянул, что это считается плохой практикой, но ответом было: «Эта служба должна работать 24 часа в сутки, 7 дней в неделю».

Поскольку у меня не было хорошего ответа о том, как правильно обрабатывать исключения в программе, которая должна работать 24/7, я сейчас здесь. Мне не удалось найти какую-либо информацию / предложения о том, как бороться с обработкой исключений в «критических» программах / службах, которые должны работать круглосуточно (и в этом случае я считаю, что это может быть нормально, если служба не работает в течение минуты или два, так что даже не критично). Я понимаю, что это зависит от точного характера программы. Требования к программе, которая может вызвать опасные для жизни проблемы, существенно отличаются от требований к сканеру журналов для онлайн-игры.

Два примера:

1: сервис опережающего ввода для клиентов Британских железных дорог, используемый при поиске в Интернете железнодорожных станций.

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

Первая программа, вероятно, не вызовет серьезной проблемы, если она остановится на минуту или две, тогда как последняя может привести к человеческим жертвам. Предложения о том, как бороться с каждым? Указатель, где я могу найти больше информации и мыслей по этому вопросу?

user1323245
источник
2
Разматывание стека во время обработки исключений в приложении реального времени (sic!) Может разрушить поезд.
Охотник на оленей
4
@DeerHunter Плохое кодирование без исключений может иметь тот же результат.
BЈовић
9
Хорошо, так что ты catch Exception. Это не означает, что ваша программа работает , это означает, что ошибки приводят к повреждению состояния приложения во время его выполнения, что является гораздо более опасным местом. Сбой программы может быть катастрофическим, но программа, которая находится в недопустимом состоянии, но все еще выполняет действия, может быть активно катастрофической.
Phoshi
1
Если приложение должно работать 24/7, где-то есть бесконечный цикл, и этот бесконечный цикл лучше обернуть вокруг какой-то конструкции, которая перехватывает все необработанные исключения. Если это не так, необработанное исключение будет применяться к уже существующему универсальному обработчику, который находится за пределами main и kaboom! 24/7 приложение заканчивается.
Дэвид Хаммен

Ответы:

7

Некоторые языковые функции, такие как

  • Вывоз мусора
  • Системы исключений
  • Ленивая оценка

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


Когда программа должна работать непрерывно, но допустимы короткие и неглобальные сбои, тогда мы можем использовать стратегию, подобную Erlang. Erlang - это параллельный, функциональный язык программирования. Обычно программа, написанная на Erlang, состоит из нескольких рабочих процессов, которые могут взаимодействовать друг с другом (модель актера). Если один рабочий поток встречает исключение, он перезапускается. Хотя это подразумевает короткое время простоя, другие актеры могут продолжать как обычно.

Подводя итог этому: в надежной программе различные части изолированы друг от друга и могут быть перезапущены или масштабированы независимо.

В общем, нам нужен кусок кода, эквивалентный этому:

while (true) {
  try {
    DoWork();
  }
  catch (Exception e) {
    log(e);
  }
}

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


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

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

Амон
источник
1
Да, но ситуация, подобная «физическому кабелю, была извлечена» именно тогда, когда вы просто хотите, чтобы журнал исключений заполнялся до тех пор, пока кто-то не подключит кабель, затем все снова начнет работать без дальнейшего перезапуска приложения вручную.
Марк Херд
2

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

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

Без обработчиков catch программа останавливает выполнение. В зависимости от ваших настроек и требований, это может быть приемлемо.

В ваших конкретных случаях:

  1. если запрос не может быть выполнен (например, неправильное название города), то сообщите пользователю об ошибке и попросите ее исправить.
  2. Если вы не получаете информацию от критически важного датчика, бессмысленно продолжать, не попросив оператора устранить проблему.

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

BЈовић
источник
1

До сих пор я ничего не видел, кроме того, что ловили базовое исключение.

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

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

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

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

Matt
источник
0

Что касается пункта 2: не используйте C #. Это не язык в реальном времени , и вы будете получать больно , если вы пытаетесь использовать его в качестве такового.

Для пункта 1: вы можете пойти по пути эрланга: пусть он рухнет, затем перезапустите

miniBill
источник
Мои знания и опыт использования C # не соответствуют пункту 2 (переключение треков в реальном времени). Мне любопытно, почему C # так не подходит для такой задачи?
Майкл О'Нил
1
В основном: сборщик мусора делает поведение программы непредсказуемым с точки зрения времени. Кроме того, среда выполнения слишком сложна, и в этих условиях вам нужны простые вещи, они более предсказуемы
miniBill
0

Заявитель: это только мысли, у меня нет опыта.

Я предполагаю, что программа, удовлетворяющая требованиям второго примера, должна быть чрезвычайно модульной . Следовательно, модули можно будет перезапустить без дестабилизации системы.

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

Более реалистично было бы ввести избыточность - дублирование аппаратного и программного обеспечения. Один экземпляр подключен к контролируемой системе, а другой - в автономном режиме. Если обнаружена ошибка, системы переключаются.

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

Vorac
источник