这将是一个很长的帖子,所以请跟我一起。
我们在几个月前在工作中实现的生产站点之一我开始经常在ELMAH日志中看到可怕的连接泄漏错误消息。
"Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached."
这让我感到困惑,因为我们正在使用EF并且连接处理应该是自动的。
所以我开始挖掘。我考虑的第一个潜在罪魁祸首是MiniProfiler(或者我应该说,我们使用miniprofiler的实现)。我们一直在使用它并且它一直运行良好,但我担心潜在的连接泄漏。
public OurContext() : base(GetProfilerConnection(), true)
{}
private static DbConnection GetProfilerConnection()
{
return new EFProfiledDbConnection(new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ConnectionString),
MiniProfiler.Current);
}
我的印象是基本调用中的“true”参数导致上下文获取连接的所有权,因此我认为这应该可以正常工作并且连接将被处理掉。
在我们的Enhancement DEV分支中,我删除了miniprofiler,因为它尚未更新以支持EF5,我们将在不久的将来进行迁移,所以这应该作为一个关注点删除。 / p>
关注二是“我们正确处理我们的数据文件”吗?所以我在试用版上下载了Entity Framework Profiler,并选择了最重的页面并进行了测试。
结果明确表明我们打开的任何上下文都是关闭的,然而我所关注的部分是我们打开的上下文的数量。我们有我的DI容器(Ninject 2)设置来为每个web http请求设置一个上下文,我就是这样 考虑正确。我们在应用程序中处理图像的方式会产生问题。特别是该页面在数据库中最多可以有七个图像。这些图像中的每一个都通过MVC动作包含在页面中。 像这样:
[<img src="/Controller/GetPhotoAction/[ImageId] />]
由于图像是一个separte请求,因此打开了一个单独的上下文。因此,对于这个特定页面,如果我正确理解这一点,我们将使用连接池中的七个不同连接。然而,无论用户多少,我都会看到这一点 上面的错误信息如何成真。
在数据库中存储图像的原因是双重的。一,我们用于管理此应用程序数据的管理应用程序位于美国西海岸,但托管该应用程序的服务器位于美国东海岸。有一个 我们的网络在西海岸工作的网络和东海岸的服务器之间的VPN隧道。该应用程序也是负载平衡(2个Web前端)。决定将图像存储在DB中以避免复制图像 通过VPN隧道,然后处理将图像写入每个服务器上的Web应用程序内的文件位置的权限(这两个位置也是完全不同的域)。
在此期间,我们测试时,我们已经在连接字符串中增加了最大连接池大小,并将在下周初将其部署到PROD。
所以,我的问题是:
1)我在这里进行泄漏检查是否覆盖了我的基地?我相信我有。我上面提到的任何内容都错了吗?
2)如果此页面上的多个数据上下文被证明是罪魁祸首,那么如何将图像写入全国各地的两台服务器并牢记权限的建议将跨域?实际上,我想要做到这一点, 但技术障碍比我们在假期前的这个时候做的要多一点。
3)如果您认为以上都不是问题,我可能会错过什么?真的是请求足够高,我们遇到了这个错误,我们需要扩展吗?我可以挖掘日志来查看使用统计信息,但它 似乎不太可能此页面缓存了一个小时(根据参数有所不同)
答案 0 :(得分:2)
有更多方法可以确定您的网络应用是否泄漏了连接。最近我受益于使用这些:
对你的问题。每个请求您应该可以使用一个数据上下文。当它被绑定到请求范围时,它将被放置在请求的末尾(实际上它被延迟,直到垃圾收集器收集请求对象)。但请注意,如果您没有直接使用您的datacontext(例如,您有一些存储库模式包装器),因为可能存在一些隐藏(连接泄漏)错误。