我们几周来一直在使用MVC应用程序遇到此问题。网站时不时会挂起。资源监视器将使用大量线程(大于100)显示应用程序。快速查看数据库(SQL Server)显示,对于每个线程,还有一个连接什么都没做(并且根本没有实际运行任何查询)。 我们查看了悬挂请求,并且有大约100个合法页面请求。我们一直在查看这些请求以寻找一些错误,但这些页面似乎都正常工作,问题似乎难以重现。 编辑:我们没有仔细查看足够的,答案就在那里。总结一下:
有谁知道可能导致此行为的原因是什么?这个问题可能(或可能不会)出现在我们的代码中,但到目前为止,它已被证明是非常难以确定的。任何线索都是最受欢迎的。
答案 0 :(得分:1)
显然很难为每个人提出答案,因为没有显示任何代码,所以这里有一些通用的建议:
提取您的数据库代码,如果您还没有,则创建类似于单独DataLayer的内容。
控制您在代码中打开的连接,确保不会发生任何事情,这意味着总是使用一个使用块,以便最后正确处理连接。
添加一些日志记录,以便您可以准确查看连接何时打开以及它们执行的操作。连接不会随机打开,这是由代码中的某些内容引起的。
确保您没有像存储库系统那样返回IQueryable东西的东西,这通常是灾难的处方。是懒惰的加载数据有时很好但是当它失控时它会咬你。
我希望自己可以提供更多帮助,但是你恐怕没有在你的问题中提出足够的细节。
答案 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是一个解答如何更好地记录挂起操作的答案。我没有最终使用它,但它让我意识到我需要做什么。