MVC应用程序挂起了很多空闲的数据库连接

时间:2016-07-08 13:00:05

标签: asp.net-mvc

我们几周来一直在使用MVC应用程序遇到此问题。网站时不时会挂起。资源监视器将使用大量线程(大于100)显示应用程序。快速查看数据库(SQL Server)显示,对于每个线程,还有一个连接什么都没做(并且根本没有实际运行任何查询)。 我们查看了悬挂请求,并且有大约100个合法页面请求。我们一直在查看这些请求以寻找一些错误,但这些页面似乎都正常工作,问题似乎难以重现。 编辑:我们没有仔细查看足够的,答案就在那里。总结一下:

  • app正常运行
  • 发生了一些不好的事情导致与数据库的连接什么都不做,但仍允许将它们设为
  • 因为这个正常的站点请求永远不会完成,并使应用程序耗尽资源(连接池和工作线程中的连接);在应用程序重新启动之前,这不会消失(或者更好的应用程序池可以回收,因为重新启动应用程序并不会杀死被绞死的线程)

有谁知道可能导致此行为的原因是什么?这个问题可能(或可能不会)出现在我们的代码中,但到目前为止,它已被证明是非常难以确定的。任何线索都是最受欢迎的。

2 个答案:

答案 0 :(得分:1)

显然很难为每个人提出答案,因为没有显示任何代码,所以这里有一些通用的建议:

  1. 提取您的数据库代码,如果您还没有,则创建类似于单独DataLayer的内容。

  2. 控制您在代码中打开的连接,确保不会发生任何事情,这意味着总是使用一个使用块,以便最后正确处理连接。

  3. 添加一些日志记录,以便您可以准确查看连接何时打开以及它们执行的操作。连接不会随机打开,这是由代码中的某些内容引起的。

  4. 确保您没有像存储库系统那样返回IQueryable东西的东西,这通常是灾难的处方。是懒惰的加载数据有时很好但是当它失控时它会咬你。

  5. 我希望自己可以提供更多帮助,但是你恐怕没有在你的问题中提出足够的细节。

答案 1 :(得分:1)

高线程数(如资源监视器所示)和SQL Server中看到的高连接数(请参阅下面的查询)表示站点范围内的挂起。

SELECT 
    DB_NAME(dbid) as DBName, 
    COUNT(dbid) as NumberOfConnections,
    loginame as LoginName
FROM
    sys.sysprocesses
WHERE 
    dbid > 0
GROUP BY 
    dbid, loginame

我预计这是一个与数据库相关的问题,因为大多数数据库连接都是空闲的(使用以下查询进行测试),但事实证明这是错误的假设。

SELECT
    S.spid,
    login_time,
    last_batch,
    status,
    hostname,
    program_name,
    cmd,
    (
        select text from sys.dm_exec_sql_text(S.sql_handle)
    ) AS last_sql
FROM
    sys.sysprocesses S
WHERE
    dbid > 0
    AND DB_NAME(dbid) = 'database_name'
    AND loginame = 'user_name'
ORDER BY last_batch ASC

我应该检查的是挂起工作线程(在IIS中选择根服务器然后是工作进程,然后是您站点的应用程序池)。获取它们的另一种方法是将其写入命令行:

%windir%\system32\inetsrv\appcmd list requests /elapsed:30000 > hanging-requests.txt

这表明挂起的原因是单个控制器操作(在挂起请求列表中始终是第一个或第二个)。我们无法在开发机器上重新创建问题,我们无法获得站点的内存转储。我们所做的是最简单和最原始的解决方案。我们写了一个简单的记录器,将数据保存到txt文件。我们用日志条目装饰了故障动作(例如"动作开始","从数据库&#34抓取模型等等)并等待发生的事情。事实证明,行动本身运作良好,但观点从未完成。然后我们开始在视图中记录内容,最终我们找到了悬挂的罪魁祸首。

罪魁祸首是一个过度设计的验证属性。该验证器也有客户端部分。简单地说,当Razor为使用此验证器装饰的字段呈现输入时,如果验证器中出现问题,它将挂起。最有可能的是它是一个放置在构造函数中的数据库连接(我们并非100%肯定)。我想,不时有一个超时会抛出异常并挂起请求(这反过来会阻止进一步的请求)。

编辑: Here是一个解答如何更好地记录挂起操作的答案。我没有最终使用它,但它让我意识到我需要做什么。