我有一台服务器托管我的网站,该网站的流量几乎为零。
每天都有一些人(< 20 人)进入该网站,并且一些 RSS 阅读器订阅了我们发布的一些提要。
几乎每天晚上,一个 RSS 阅读器都会在半夜打到我们,并得到一个异常,即网站由于连接超时而无法连接到 SQL Server。细节非常奇怪,所以我正在寻找可能是什么问题的帮助,因为我不知道从哪里开始寻找了。
我们在 Windows Server 2008 上使用 ASP.Net MVC、Entity Framework 和 SQL Server 2008。这台机器是我们从不完全是顶级供应商那里获得的专用机器,因此可能配置不理想,或者谁知道什么别的。
盒子也很小,只有 1Gb RAM,但它应该能承受我们现在的负载......
我正在复制下面的完整调用堆栈,但首先,我们知道一些事情:
- 当 iTunes 查询我们的网站时,总是会发生错误。我相信这应该与任何事情无关,但事实是我们只能从 iTunes 获得它。我最好的猜测是,发生这种情况是因为只有 iTunes 在晚上没有其他人打我们的时候查询我们。
- 我们的理论之一是 SQL Server 和 IIS 正在争夺内存,其中一个因未使用而被分页到磁盘,当有人“唤醒它”时,从磁盘读取所有内容需要很长时间进入记忆。这是可能发生的事情吗?(我有点放弃这个,因为如果可能的话,这听起来像是 SQL Server 中的一个设计问题)
- 我还考虑了我们泄漏连接的可能性,因为我们可能没有适当地处理 EF 实体(请参阅我的问题here)。这是我通过谷歌搜索问题唯一能找到的。考虑到我们的负载极低,我放弃了这个。
- 这总是在晚上发生,所以很可能与一段时间内什么都没有发生有关。例如,我很确定当这些请求命中时,Web 服务器进程被回收,它正在启动/重新 JIT 处理所有内容。但是,重新 JITting 并没有解释 SQL 超时。
更新:我们按照建议附加了一个分析器,我们花了很长时间才发现一个新的异常。这是我们知道的新东西:
- 附加分析器极大地减少了我们得到的错误数量。事实上,在正常情况下每天获得几个之后,我们不得不等待 3 或 4 天才能发生一次。一旦我们停止分析器,它就会回到正常的错误频率(甚至更糟)。所以 profiler 有一些效果,在一定程度上隐藏了这个问题,但不是完全隐藏。
- 查看 IIS 请求日志旁边的探查器跟踪,请求和查询之间存在预期的 1-1 对应关系。但是,时不时地,我会看到很多正在执行的查询与 IIS 日志完全没有关联。事实上,在记录实际错误之前,我在 3 分钟内收到了 750 个查询,所有这些都与 IIS 日志完全无关。查询文本看起来像 EF 生成的那种不可读的废话,它们并不完全相同,它们看起来都像来自网站的查询:相同的应用程序名称、用户等。让我们知道这有多荒谬也就是说,该站点在2 天内收到了大约 370 个访问数据库的 IIS 请求
- 这些无法解释的查询与之前的网站查询并非来自相同的 ClientProcessID,尽管如果进程在此期间被回收,它们可能仍然来自网站。在最后一个解释的查询和第一个无法解释的查询之间几乎有一个小时没有活动。
- 我不知道它们来自哪里的这些长串查询之一就在我记录错误之前出现,所以我相信这是我们应该遵循的线索。
- 正如我最初预期的那样,当引发错误的查询被执行时,它来自与前一个不同的 ClientProcessID,(比前一个无法解释的晚 8 分钟,比前一个 IIS 晚几乎一小时)。这意味着,对我来说,工作进程确实已经被回收了。
- 这是我完全不明白的。IIS 日志显示,在错误请求前一分钟,有 4 个得到了完美的服务,尽管这些查询根本没有显示在跟踪中。事实上,在这 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)
任何想法将不胜感激。