Khe*_*pri 10 .net asp.net-mvc ado.net ninject entity-framework-4
这将是一个很长的帖子,所以请跟我一起.
我们在几个月前在工作中实现的生产站点之一,我开始经常在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."
Run Code Online (Sandbox Code Playgroud)
这让我感到困惑,因为我们正在使用EF并且连接处理应该是自动的.
所以我开始挖掘.我考虑的第一个潜在罪魁祸首是MiniProfiler(或者我应该说,我们使用miniprofiler的实现).我们一直在使用它并且它一直运行良好,但我担心潜在的连接泄漏.
public OurContext() : base(GetProfilerConnection(), true)
{}
private static DbConnection GetProfilerConnection()
{
return new EFProfiledDbConnection(new SqlConnection(ConfigurationManager.ConnectionStrings["Database"].ConnectionString),
MiniProfiler.Current);
}
Run Code Online (Sandbox Code Playgroud)
我的印象是基本调用中的"true"参数导致上下文获取连接的所有权,所以我认为这应该正常工作并且连接将被处理掉.

在我们的Enhancement DEV分支中,我删除了miniprofiler,因为它尚未更新以支持EF5,我们将在不久的将来进行迁移,所以这应该作为一个问题删除.
值得关注的是"我们正确处理我们的datacontexts"吗?所以我在试用版上下载了Entity Framework Profiler并拿走了我们最重的页面并进行了测试.

结果明确表明,我们打开的任何背景都是封闭的,然而我所关注的部分是我们打开的背景数量.我们的DI容器(Ninject 2)设置为每个Web http请求设置一个上下文,我认为这是正确的.我们在应用程序中处理图像的方式会产生问题.特别是该页面在数据库中最多可以有七个图像.这些图像中的每一个都通过MVC动作包含在页面中.像这样:
[<img src="/Controller/GetPhotoAction/[ImageId] />]
Run Code Online (Sandbox Code Playgroud)
由于图像是separte请求,因此打开单独的上下文.因此,对于这个特定页面,如果我正确理解这一点,我们将使用连接池中的七个不同连接.无论多少用户乘以此,我都会看到上面的错误消息是真的.
将图像存储在数据库中的原因是双重的.一,我们用于管理此应用程序数据的管理应用程序位于美国西海岸,但托管该应用程序的服务器位于美国东海岸.我们的网络在西海岸工作和东海岸的服务器之间有一条VPN隧道.该应用程序也是负载平衡(2个Web前端).决定将图像存储在数据库中以避免通过VPN隧道复制图像,然后处理将图像写入每个服务器上的Web应用程序内的文件位置的权限(这两个位置也是完全不同的域) .
在此期间,我们测试时,我们已经在连接字符串中增加了最大连接池大小,并将在下周初将其部署到PROD.
所以,我的问题是:
1)我在这里进行泄漏检查是否覆盖了我的基地?我相信我有.我在上面提到的任何事情都错了吗?
2)如果此页面上的多个数据上下文被证明是罪魁祸首,那么关于如何将图像写入全国两个服务器并牢记权限的建议将跨域?实际上,我想要做到这一点,但技术障碍比我们在假期前的这个时候愿意做的多一点.
3)如果您认为以上都不是问题,我可能会错过什么?真的是请求足够高,我们遇到了这个错误,我们需要扩展吗?我可以挖掘日志来查看使用统计信息,但似乎不太可能.此页面缓存了一个小时(根据参数有所不同)
有更多方法可以确定您的网络应用程序是否泄漏连接。最近我从使用这些中受益:
对于你的问题。您应该可以接受每个请求一个数据上下文。当它绑定到请求范围时,它将在请求结束时被释放(实际上它会被延迟,直到垃圾收集器收集请求对象)。但请注意,如果您不直接使用数据上下文(例如,您有一些存储库模式包装器),因为可能存在一些隐藏的(连接泄漏)错误。