Подтвердить что ты не робот

Помощь по устранению неполадок SqlException: время ожидания истекло при подключении, в ситуации без нагрузки

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

Почти каждую ночь читатель RSS попадет нам посреди ночи и получит исключение, которое веб-сайт не может подключиться к SQL Server из-за таймаута в соединении. Детали чрезвычайно странные, поэтому я ищу какую-то помощь в том, что может быть проблемой, так как я не знаю, с чего начать больше.

Мы используем ASP.Net MVC, Entity Framework и SQL Server 2008 по сравнению с Windows Server 2008. Машина представляет собой выделенную ячейку, которую мы получили от не совсем высшего провайдера, поэтому все может быть настроено не оптимально или кто знает, что еще. Коробка также довольно маленькая и имеет только 1 ГБ оперативной памяти, но она должна взять ту нагрузку, которую мы имеем сейчас...

Я копирую полный стек вызовов ниже, но сначала некоторые из вещей, которые мы знаем:

  • Ошибка всегда возникает, когда iTunes запрашивает наш сайт. Я считаю, что это ничего не должно делать, но правда в том, что мы получаем его только от iTunes. Мое лучшее предположение, что это происходит, потому что только iTunes запрашивает нас в то время ночи, когда никто больше не наносит нам удар.
  • Одна из наших теорий заключается в том, что SQL Server и IIS борются за память, и один из них выгружается на диск из-за того, что он не используется, а когда кто-то "просыпается", слишком много времени, чтобы читать все с диска обратно в память. Возможно ли, что это может произойти? (Я отбрасываю это, так как это звучит как проблема дизайна в SQL Server, если это было возможно).
  • Я также подумал о возможности утечки соединений, поскольку мы не можем распоряжаться объектами EF соответствующим образом (см. мой вопрос здесь). Это единственное, что я смог найти по проблеме Googling. Я отбрасываю это, учитывая крайне низкую нагрузку, которую мы имеем.
  • Это всегда происходит ночью, поэтому очень вероятно, что что-то связано с тем, что на какое-то время ничего не происходило. Например, я уверен, что когда эти запросы попали, процесс веб-сервера переработал, и он запустил/перезаписал все. Однако повторное JITting не объясняет тайм-аут SQL.

ОБНОВЛЕНИЕ:. Мы приложили профайлер, как было предложено, и потребовалось довольно много времени, прежде чем у нас появилось новое исключение. Это новый материал, который мы знаем:

  • Наличие профайлера чрезвычайно уменьшило количество ошибок, которые мы получили. Фактически, после обычного получения нескольких в день, нам пришлось ждать 3 или 4 дня, чтобы это произошло ТОЛЬКО. Как только мы остановили профайлер, он вернулся к нормальной частоте ошибок (или даже хуже). Таким образом, профилировщик имеет некоторый эффект, который скрывает эту проблему до некоторой степени, но не полностью.
  • Рассматривая трассировку профилировщика рядом с журналом запросов IIS, существует ожидаемое соответствие между запросами и запросами 1-1. Тем не менее, время от времени я вижу много выполненных запросов, которые не имеют никакой корреляции с журналом IIS. Фактически, до того, как была зарегистрирована реальная ошибка, я получил 750 запросов в течение 3 минут, все из которых были полностью не связаны с журналами IIS. Текст запроса выглядит как нечитаемое дерьмо, которое генерирует EF, и они не все одинаковые, и все они выглядят так же, как запросы, поступающие с веб-сайта: Same ApplicationName, User и т.д. Чтобы дать представление о том, насколько смешно это, сайт получил около 370 запросов IIS, которые попали в БД, в течение 2 дней
  • Эти необъяснимые запросы не исходили от одного и того же ClientProcessID, как и предыдущие веб-сайты, хотя они все равно могут поступать с веб-сайта, если процесс переработан в то же время. Был почти час отсутствия активности между последним объясненным запросом и первым необъяснимым.
  • Одна из этих длинных строк запросов, которые я не знаю, откуда они пришли, произошла прямо перед ошибкой, которую я зарегистрировал, поэтому я считаю, что это ключ, по которому мы должны следовать.
  • Как я и ожидал, когда запрос, который запустил ошибку, был выполнен, он исходил из другого ClientProcessID, чем предыдущий, (на 8 минут позже предыдущего необъясненного и почти на один час позже предыдущего IIS). Это означает для меня, что рабочий процесс действительно получил рециркуляцию.
  • Это то, что я абсолютно не понимаю. Журнал IIS показывает, что за одну минуту до запросов об ошибках 4 были отлично поданы, хотя запросы для них вообще не отображаются в трассировке. Фактически, после того, как все прошло хорошо, у меня было 4 исключения, которые были быстро выбраны, эти 4 ТАКЖЕ не отображаются в трассировке (что имеет смысл, поскольку, если в связи с этим был тайм-аут, запрос никогда не должен выполняться, но я не вижу попыток соединения в трассировке)

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

Любые идеи?


Это информация об исключении:

System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.

System.Data.EntityException: The underlying provider failed on Open. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
   at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   at System.Data.SqlClient.SqlConnection.Open()
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   --- End of inner exception stack trace ---
   at System.Data.EntityClient.EntityConnection.OpenStoreConnectionIf(Boolean openCondition, DbConnection storeConnectionToOpen, DbConnection originalConnection, String exceptionCode, String attemptedOperation, Boolean& closeStoreConnectionOnFailure)
   at System.Data.EntityClient.EntityConnection.Open()
   at System.Data.Objects.ObjectContext.EnsureConnection()
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__1[TResult](IEnumerable`1 sequence)
   at System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
   at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
   at MyProject.Controllers.SitesController.Feed(Int32 id) in C:\...\Controller.cs:line 38
   at lambda_method(ExecutionScope , ControllerBase , Object[] )
   at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassa.<InvokeActionMethodWithFilters>b__7()
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
   at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.ProcessRequest(HttpContextBase httpContext)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Любые идеи будут чрезвычайно оценены.

4b9b3361

Ответ 1

Недостаточная память

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

Легко проверить возможности:

  • У вас может быть включен "Автоматическое закрытие": Auto Close может иметь именно такое поведение, однако его редко можно включить. Чтобы проверить это, в SSMS щелкните правой кнопкой мыши по базе данных приложений, выберите "Свойства", а затем выберите панель "Параметры". Посмотрите на запись "Auto Close" и убедитесь, что она установлена ​​в False. Также проверьте tempdb.

  • Задания SQL-агента могут быть причиной этого: проверьте журнал событий агента, чтобы узнать, были ли какие-либо задания, постоянно выполняемые во время событий. Не забудьте также проверить работу по техническому обслуживанию, поскольку такие вещи, как "Индексы перестройки", часто упоминаются как проблемы с производительностью во время их работы. Сейчас это маловероятные кандидаты, только потому, что они обычно не будут затронуты Профайлером.

Почему это выглядит как проблема памяти:

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

  • У вас есть 1 ГБ памяти: хотя это технически выше минимального для SQL Server, это ниже рекомендованного для SQL Server способа и ниже, что по моему опыту приемлемо для производства, даже для слегка загруженный сервер.

  • Вы используете IIS и SQL Server в одном и том же поле: это само по себе не рекомендуется, в основном из-за конкуренции за память, которая получается, но с 1 ГБ памяти это приводит к IIS, приложение, SQL Server, ОС и любые другие задачи и/или обслуживание, все сражаются за очень мало памяти. То, как Windows управляет этим, - это дать памяти активным процессам, агрессивно отвлекая их от неактивных процессов. Может потребоваться много секунд или даже минут для большого процесса, такого как SQL Server, чтобы получить достаточно памяти, чтобы иметь возможность полностью обслуживать запрос в этой ситуации.

  • Профайлер заставил 90% проблемы уйти: это большой ключ к тому, что память, вероятно, является проблемой, поскольку, как правило, такие вещи, как Profiler, имеют именно такой эффект для этой конкретной проблемы: задача Profiler хранит SQL Server просто немного активны все время. Часто это всего лишь активность, чтобы либо сохранить ее в списке OS "scavenger", либо, по крайней мере, уменьшить ее влияние.

Как проверить память как виновника:

  • Отключить профайлер: он имеет эффект Гейзенберга на проблему, поэтому вам нужно отключить его, иначе вы не сможете увидеть проблему надежно.

  • Запустите системный монитор (perfmon.exe) из другого окна, который удаленно подключается к службе сбора парфюмеров в поле, в котором работают ваш SQL Server и IIS. вы можете легко сделать это, сначала удалив три значения по умолчанию (они только локальные), а затем добавьте необходимую статистику (см. ниже), но не забудьте изменить имя компьютера в первом раскрывающемся списке, чтобы подключиться к вашему SQL коробка.

  • Отправьте собранные данные в файл, создав "Counter Log" на perfmon. Если вы не знакомы с этим, то самое легкое, что нужно сделать, это, вероятно, собрать данные в файл с вкладкой или запятой, который можно открыть с помощью Excel для анализа.

  • Настройте свой perfmon для сбора в файл и добавьте к нему следующие счетчики:

    - Процессор\%Время процессора [Всего]

    - PhysicalDisk\%Время ожидания [для каждого диска]

    - PhysicalDisk\Avg. Длина очереди диска [для каждого диска]

    - Память\Страницы/сек

    - Память\Чтение страниц/сек

    - Память\Доступные MBytes

    - Сетевой интерфейс\Байты Всего/сек [для каждого используемого интерфейса]

    - Процесс\%Время процессора [см. ниже]

    - Процесс\Страница Неисправности/сек [см. ниже]

    - Процесс\Рабочий набор [см. ниже]

  • Для счетчиков Process (выше) вы хотите включить процесс sqlserver.exe, любые процессы IIS и любые стабильные процессы приложений. Обратите внимание, что это будет ТОЛЬКО работать для "стабильных" процессов. Процессы, которые постоянно воссоздаются по мере необходимости, не могут быть захвачены таким образом, потому что нет способа указать их до их существования.

  • Запустите эту коллекцию в файл в течение времени, когда проблема чаще всего возникает. Установите интервал сбора примерно на 10-15 секунд. (это собирает много данных, но вам понадобится это разрешение, чтобы выделить отдельные события).

  • После того, как у вас есть один или несколько инцидентов, остановите сборку, а затем откройте файл собранных данных в Excel. Вам, вероятно, придется переформатировать столбец timestamp, чтобы он был полезен и показывал часы минут и секунд. Используйте журнал IIS, чтобы узнать точное время инцидентов, а затем посмотрите данные perfmon, чтобы узнать, что происходит до и после инцидента. В частности, вы хотите увидеть, был ли его рабочий набор небольшим раньше и был большим после, с большим количеством ошибок страниц между ними. Это самый яркий признак этой проблемы.

SOLUTIONS:

Разделяйте IIS и SQL Server на два разных поля (желательно) или добавьте больше памяти в поле. Я думаю, что 3-4 ГБ должны быть минимальными.

Что относительно этого странного EF-материала?

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

Ответ 2

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

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

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

РЕДАКТИРОВАТЬ: Адресация вашего обновления.

Обновляется/создается EF его кеш? Он может объяснить обилие запросов за один раз и почему запросы не попали в базу данных позже.

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

Ответ 3

Он пахнет крохотной штукой, которая работает одновременно. Как пишет RBarryYoung, некоторые ночные резервные копии, или это может быть что-то еще У вас есть root-доступ к серверу? Вы видите кронаб?

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

Ответ 4

В моем случае, когда я установил sqlserver 2008 r2 sp3, проблема исчезнет.

Сервер: клиент Windows 7 + SqlServer 2008 R2 (разработчик): Raspberrypi 3B+, Core Asp.net Core + EF