Как устранить внезапную потерю подключения к SQL Azure в моей роли Azure?

Моя роль Azure забирает данные для обработки из базы данных — она содержит экземпляр System.Data.SqlClient.SqlConnection, периодически создает экземпляр SqlCommand и выполняет SQL-запрос.

Теперь время от времени (обычно раз в несколько дней) запуск запроса будет вызывать исключение SqlException

Сервис обнаружил ошибку при обработке вашего запроса. Пожалуйста, попробуйте еще раз. Код ошибки 40143. В текущей команде произошла серьезная ошибка. Результаты, если таковые имеются, должны быть отброшены.

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

Время ожидания истекло. Время ожидания истекло до завершения операции или сервер не отвечает.

Это очень похоже на то, что сервер SQL Azure не отвечает или недоступен по какой-либо причине.

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

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

Какой должна быть стратегия решения этой проблемы? Должен ли я повторить запрос несколько раз и сколько раз и с каким интервалом? Должен ли я сделать что-то еще? Когда я сдаюсь и позволяю роли просто перезапуститься?


person sharptooth    schedule 10.08.2011    source источник


Ответы (2)


Я настоятельно рекомендую вам ознакомиться с платформой обработки переходных сбоев для SQL Azure.

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

[РЕДАКТИРОВАТЬ: 17 октября 2013 г.]

Похоже, что это было подхвачено группой шаблонов и практик по адресу Прикладной блок обработки временных сбоев

person David Steele    schedule 10.08.2011
comment
Он также доступен через nuget. - person dunnry; 10.08.2011
comment
Спасибо, Даннри, я этого не заметил. Я виню Уэйда в том, что он не держал нас в курсе событий ;) - person David Steele; 11.08.2011
comment
Этот сайт обработки переходных сбоев имеет непреодолимую ошибку: не работает. - person Rory; 06.09.2013
comment
А сейчас он устарел, и нет поддерживаемого решения. - person O'Rooney; 21.10.2015

Мы используем TransientFaultHandling, и он не обрабатывает все странные исключения.

Например, вчера выскочило вот это:

Сервис обнаружил ошибку при обработке вашего запроса. Пожалуйста, попробуйте еще раз. Код ошибки 40143. В текущей команде произошла серьезная ошибка. Результаты, если таковые имеются, должны быть отброшены. , трассировка стека в System.Data.SqlClient.SqlConnection.OnError (исключение SqlException, логическое значение breakConnection) в System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() в System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, . . . .

Разумный подход, который будет работать даже с этим:

  1. Определите грубую псевдотранзакцию, в которой происходит вызов.
  2. Оберните этот блок в try-catch.
  3. в исключительных случаях «откатывать» псевдотранзакцию.

Пример типичного рабочего процесса:

  • Сообщение о получении очереди Azure
  • B запросить данные из SQL Azure
  • C данные процесса,
  • D загрузить результаты
  • E удалить сообщение.

Оберните B через C вместе в try-catch. Если что-то произойдет во время «безобидного» вызова SQL Azure, просто выйдите из системы, не удаляя сообщение, оно просто появится снова после истечения времени ожидания видимости.

На самом деле, это очень распространенный подход: организовывать в блоки, подобные транзакциям, оборачивать блок в try-catch, аккуратно откатывать при исключении. И никогда, никогда не предполагайте, что некоторые вызовы не завершатся ошибкой. Все вызовы время от времени терпят неудачу.

person Sergey Malgin    schedule 07.12.2012
comment
Я согласен с вашим подходом, но ответ Дэвида Стила также правильный. На самом деле оба ответа касаются разных уровней. Вы используете Transient Fault Handling Framework для обработки временных ошибок; если ситуация сохраняется, вы прерываете текущую операцию и повторяете ее позже (или отбрасываете). - person Fernando Correia; 07.12.2012