У меня есть сервер, на котором размещен мой сайт, который имеет почти нулевой трафик.
Несколько человек (< 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)
Любые идеи будут чрезвычайно оценены.