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

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

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

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

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

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

Что выглядит так, как сервер SQL Azure не отвечает или недоступен по любой причине.

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

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

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

Ответ 1

Я бы настоятельно рекомендовал вам взглянуть на Transion Fault Handling Framework для SQL Azure

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

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

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

Ответ 2

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

Например, вчерашний всплыл:

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

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

  • Определите крупнозернистую псевдо-транзакцию, в которой происходит вызов.
  • Оберните этот блок в try-catch.
  • для исключения, "откат" псевдо-транзакции.

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

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

Оберните B через C вместе в попытке. Если что-то происходит во время "безобидного" вызова SQL Azure, просто выйдите из него, не удаляя сообщение, оно просто появится снова после истечения таймаута видимости.

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