Отказоустойчивый экземпляр кластера SQL Server 2014, как повторно подключиться при отказе?

Я установил отказоустойчивый кластер Windows Server в тестовой среде и установил на нем кластерный экземпляр SQL Server 2014. Кластер состоит из двух узлов, а имя сети - SQLINSTANCE.

Теперь из небольшого консольного приложения у меня есть простой цикл (который работает нормально), который запрашивает тестовую базу данных каждые 100 мс:

while (true)
{
   using (var dbContext = new TestDBContext())
   {
       foreach (var person in dbContext.People)
       {
            Console.WriteLine(person.FirstName + " " + person.LastName);
            System.Threading.Thread.Sleep(100);
       }
    } 
 }

Теперь я принудительно выполняю аварийное переключение в кластере (либо путем выключения одного узла, либо путем перемещения роли SQL-сервера на другой узел из диспетчера кластеров). Процесс переключения при отказе занимает около 50 секунд. Когда отработка отказа завершена, мой тестовый цикл генерирует исключение EntityException, говоря, что «базовый поставщик отказал при открытии». InnerException - это SqlClient.SqlException, в котором говорится: «Невозможно открыть базу данных« TestDB », запрошенную при входе в систему. Ошибка входа в систему. Ошибка входа для пользователя« Домен \ Пользователь »».

Я установил свою строку подключения следующим образом:

 <add name="TestDBEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;
         provider connection string=&quot;data source=sqlinstance;initial catalog=TestDB;integrated security=True;
         MultiSubnetFailover=true;
         connect timeout=150;
         ConnectRetryCount=15;
         ConnectRetryInterval=10;
         MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

Я ожидал, что SqlClient попытается повторно подключиться к моему экземпляру clusterd 15 раз с интервалом в 10 секунд, а затем успешно повторно подключится, когда отработка отказа завершится. Но он по-прежнему выбрасывает исключения.

Я попытался изменить значения «Тайм-аут подключения», «ConnectRetryCount» и «ConnectRetryInterval», но все равно не удалось полностью восстановить подключение после аварийного переключения ...

Я очень запутался, чего мне здесь не хватает, или я могу не полагаться на базовый SqlClient, и должен ли я, например, предоставлять свою логику повтора owm в DAL ???


person Jeroen1984    schedule 18.12.2014    source источник
comment
А исключение есть? Я спрашиваю, потому что, вероятно, отработка отказа завершена, но не все базы данных подключены к сети ...   -  person user_0    schedule 18.12.2014
comment
Это EntityException, говорящее о том, что базовый провайдер не удалось открыть. InnerException - это SqlClient.SqlException, в котором говорится, что невозможно открыть базу данных TestDB, запрошенную при входе в систему. Не удалось войти в систему. Не удалось войти в систему для пользователя «Домен \ Пользователь». Он запускается в момент завершения отработки отказа. Кстати, я также отредактировал свое сообщение с этой подробной информацией об исключении ...   -  person Jeroen1984    schedule 18.12.2014
comment
Проблема в том, что невозможно открыть базу данных. Почему это приложение? Каждый раз, когда вы перезапускаете SQL Server, ему необходимо выполнить некоторую проверку базы данных. В зависимости от размера и незавершенных транзакций это может занять от секунд до дней. Вы можете проверить это в журнале ошибок. Вы найдете такие сообщения, как «Запуск базы данных dbname» и другие, дающие вам информацию о статусе проверки.   -  person user_0    schedule 18.12.2014
comment
@ user_0, ладно, звучит разумно. Итак, экземпляр запущен, мое приложение может установить соединение, но база данных еще недоступна ... Вы знаете какие-либо решения для этого, возможно, встроенные в .NET Framework? Я читал кое-что о стратегиях выполнения EF6 и SqlAzureExecutionStrategy. Знаете ли вы, подходит ли это, или я должен предоставить свою собственную логику?   -  person Jeroen1984    schedule 18.12.2014
comment
Не уверен в этом, извините. У меня есть услуги на разных языках. Обычно они обновляют соединения каждый раз x (переменная x в зависимости от типа службы или приложения)   -  person user_0    schedule 18.12.2014
comment
@ user_0 Хорошо, спасибо за ваш вклад!   -  person Jeroen1984    schedule 18.12.2014


Ответы (1)


Я не эксперт во всем этом, особенно я не уверен, как C # обрабатывает соединение с базой данных. В одном из наших приложений я видел, что вы открываете соединение с db в кластере AlwaysOn, и когда вы сбрасываете приложение, соединение по-прежнему использует то же базовое TCP-соединение, которое фактически идет к узлу, который к настоящему времени имеет измененный. Для нас решением было правильное переподключение при обнаружении исключения.

person ikkjo    schedule 17.04.2015
comment
Привет @ikkjo. Наткнулся на этот твой ответ. Я думаю, что мы сталкиваемся с аналогичной ситуацией в нашей среде, несмотря на аварийное переключение, приложение все еще подключается к тому, что сейчас является вторичным узлом. Не могли бы вы подробнее рассказать, какое решение было для вас? - person Crabster; 09.10.2015
comment
Привет @Crabster. Не уверен, что могу дать вам намного больше. Приложение уже проверило состояние соединения с базой данных и попыталось восстановить соединение при разрыве соединения. Однако при попытке зафиксировать изменение в базе данных мы получили исключение. В конечном итоге все свелось к следующему (хотя я не уверен на 100%): произошла ошибка транспортного уровня при отправке запроса на сервер. (поставщик: поставщик TCP, ошибка: 0 - существующее соединение было принудительно закрыто удаленным хостом.) Итак, мы перехватили исключение и повторно открыли соединение с базой данных. - person ikkjo; 10.10.2015