FIFO队列导致IIS处理器达到100%的最大值
本文关键字:100% 最大值 处理器 队列 IIS FIFO | 更新日期: 2023-09-27 17:51:11
我在IIS上有一个单例服务类,作为web应用程序的一部分(出于数据缓存的原因,该服务是单例的)。向服务发出请求的浏览器客户端可以得到以下三种结果之一:
1)缓存中有数据并且数据没有过期(过期)-我们返回该数据。非常快。2)缓存的数据已经过期,但是另一个请求已经在查询数据库。我们返回缓存的数据。3)缓存的数据过期,没有请求对DB进行查询。该请求向前移动以进行查询。
但是,针对同名存储过程的数据库查询必须排队(需求)。
因此,我编写了这个queue类,它被设计成将这些查询排队并连续运行,而不是并发运行。这些队列类是根据需要创建的,并存储在单例类的列表中。当请求移动到第(3)部分时,它会找到与其存储过程名称匹配的队列类,并将请求提交给队列类。然后,它等待数据从DB返回,以便为HTML请求提供服务。不幸的是,在这段代码运行了几个小时后,服务器进程达到了100%的最大值。我不确定最好的方法是去改进它,因为多线程编码不是我的专长。
队列类代码如下所示:
public ReportTable GetReportTable(ReportQuery query)
{
lock (_queue)
{
_queue.Enqueue(query);
Monitor.Pulse(_queue);
}
lock (_queue)
{
var firstQueryInQueue = _queue.Peek();
while (_inUse || firstQueryInQueue == null || firstQueryInQueue.GetHashCode() != query.GetHashCode())
{
Monitor.Pulse(_queue);
Monitor.Wait(_queue);
}
_inUse = true;
firstQueryInQueue = _queue.Dequeue();
var table = firstQueryInQueue.GetNewReportTable();
_inUse = false;
Monitor.Pulse(_queue);
return table;
}
}
我不知道我是否理解问题但是你可以很简单地重写
private object _lockObj=new object();
public ReportTable GetReportTable(ReportQuery query)
{
lock(_lockObj){
var table = query.GetNewReportTable();
return table;
}
}
我是这么做的。
public ReportTable GetReportTable(ReportQuery query)
{
lock (_queue)
{
_queue.Enqueue(query);
Monitor.Pulse(_queue);
}
lock (_queue)
{
var firstQueryInQueue = _queue.Peek();
while (_inUse || firstQueryInQueue == null || firstQueryInQueue.GetHashCode() != query.GetHashCode())
{
Monitor.Wait(_queue);
}
_inUse = true;
firstQueryInQueue = _queue.Dequeue();
var table = firstQueryInQueue.GetNewReportTable();
_inUse = false;
Monitor.Pulse(_queue);
return table;
}
}
之前没有工作的原因是因为我对Monitor.Wait()和Monitor.Pulse()缺乏全面的了解。我在代码中的错误位置使用Pulse()。幸运的是,这里有一个很好的答案,它很好地描述了Wait()和Pulse()。
关键是在集合更改后使用Pulse(),并为后续排队线程提供测试条件的机会,该条件是:我的查询是否在队列中第一个?是否已经有人提出疑问了?如果测试失败,线程调用Wait(),这会将其放入等待队列中,并且不会占用处理器周期。当在前面并且正在执行查询的线程完成时,它将_inUse标志翻转为false并调用Pulse(),唤醒下一个线程之一,以便检查条件。
在执行此解决方案并观察任务管理器一天后,我很高兴地看到服务器上的负载为1%到5%,并且CPU从未像以前那样爬升到100%。
我对此做了很多阅读,似乎PulseAll()在这种情况下可能是更好的调用,但到目前为止Pulse()正在工作,我们还没有遇到任何问题。