Правильная реализация временной обработки сбоев (Azure)

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

До сих пор мой подход включал

public static void SetRetryStratPol()
{
    const string defaultRetryStrategyName = "default";

    var strategy = new Incremental(defaultRetryStrategyName, 3, TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2));
    var strategies = new List<RetryStrategy> { strategy };
    var manager = new RetryManager(strategies, defaultRetryStrategyName);
    RetryManager.SetDefault(manager);
    retryPolicy = new RetryPolicy<SqlDatabaseTransientErrorDetectionStrategy>(strategy);
    retryPolicy.Retrying += (obj, eventArgs) =>
                            {
                                var msg = String.Format("Retrying, CurrentRetryCount = {0} , Delay = {1}, Exception = {2}", eventArgs.CurrentRetryCount, eventArgs.Delay, eventArgs.LastException.Message);
                                System.Diagnostics.Debug.WriteLine(msg);
                            };
}

Я вызываю этот метод из Global.asax, Application_Start(). [retryPolicy — это глобальная статическая переменная в статическом классе, который также включает следующий метод.]

Затем у меня есть метод

public static ReliableSqlConnection GetReliableConnection()
{
    var conn = new ReliableSqlConnection("Server=...,1433;Database=...;User ID=...;Password=...;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;", retryPolicy);

    conn.Open();

    return conn;
}

Затем я использую этот метод

using (var conn = GetReliableConnection())
using (var cmd = conn.CreateCommand())
{
    cmd.CommandText = "SELECT COUNT(*) FROM ReliabilityTest";

    result = (int) cmd.ExecuteScalarWithRetry();

    return View(result);
}

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

Но когда я прохожу этот код, курсор сразу же переходит к моей инструкции catch с

Ошибка входа для пользователя «[мое имя пользователя]».

Я ожидал, что это исключение будет перехвачено только через несколько секунд, но никакой задержки не возникает.

Кроме того, я также пытался использовать Entity Framework, точно следуя это сообщение, но получите тот же результат.

Что я пропустил? Есть ли этап настройки или я неправильно вызываю временную ошибку?


person awj    schedule 06.01.2015    source источник


Ответы (1)


Блок Transient Fault Handling предназначен для обработки временных ошибок. Неудачный вход из-за неправильного имени пользователя/пароля, безусловно, не является одним из них. На этой веб-странице: http://msdn.microsoft.com/en-us/library/dn440719%28v=pandp.60%29.aspx:

Что такое временные сбои?

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

Вы можете проверить исходный код этого блока приложения (http://topaz.codeplex.com/) и посмотреть, какие коды ошибок возвращаемые из баз данных SQL, считаются временными ошибками и поэтому повторяются.

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

ОБНОВЛЕНИЕ

Взгляните на исходный код здесь: http://topaz.codeplex.com/SourceControl/latest#source/Source/TransientFaultHandling.Data/SqlDatabaseTransientErrorDetectionStrategy.cs. Здесь происходит магия повторных попыток. Что вы можете сделать, так это создать класс (назовем его CustomSqlDatabaseTransientErrorDetectionStrategy) и скопировать весь код из ссылки в этот класс). Затем для целей тестирования вы можете добавить сценарий login failed в качестве одной из временных ошибок и использовать этот класс в своем приложении вместо SqlDatabaseTransientErrorDetectionStrategy.

person Gaurav Mantri    schedule 06.01.2015
comment
Это было одним из моих подозрений. Однако сообщение в блоге, на которое я ссылался в вопросе, было написано 6 месяцев назад Azure MVP, и он вызывает политику повторных попыток, изменив имя пользователя, а затем предоставляет доказательство того, что это изменение вызвало политику повторных попыток. Есть ли у вас опыт работы с обработкой переходных сбоев и можете ли вы предложить какой-либо другой способ его проверки? - person awj; 06.01.2015
comment
Обновил мой ответ. ХТН. - person Gaurav Mantri; 06.01.2015
comment
Я искал исходный код, но не нашел его, так что спасибо за ссылку. Я сделал, как вы предложили, и обнаружил, что коды ошибок, которые я вызывал, не относятся к тому типу, который считается временным сбоем. Однако я мог видеть, что он неоднократно использовал метод IsTransient в соответствии с RetryStrategy. Итак... Теперь я вполне удовлетворен тем, что код в моем OP действителен, я просто пытался запустить и проверить его неправильно. Спасибо за вашу помощь. - person awj; 06.01.2015
comment
Обратите внимание, что сами Microsoft постоянно дополняют список временных ошибок. Так что я не думаю, что его можно считать авторитетным даже в какой-то момент времени, потому что разные команды в MS делают разные вещи. Мы упорствовали какое-то время, но каждый раз, когда мы думали, что добились прогресса, возникала новая ошибка, которая не была исправлена. Итак, что мы сделали, так это повторили попытку для всех ошибок, с несколькими серьезными ошибками, которые мы вносим в белый список как не заслуживающие повторной попытки. - person O'Rooney; 17.11.2015