我们有一个常见的日志记录问题,我们做3种类型的日志记录(让我们说:跟踪,审计,计数)是我们记录的3个方面。我们同时从REST Web服务中运行的代码为每个请求提供所有请求。生产者 - 消费者多个生产者多个队列单个消费者
对于每个请求,我们会对每个日志记录区域进行多次调用。比方说,平均每个Web请求约100次日志调用,一些跟踪,一些审计,一些计数器,总共100次调用,每个Web请求。每个日志记录调用都会将一些数据写入某个存储以供稍后处理[不重要的是该存储是什么,但将其存入该存储肯定是I/O绑定的 - (实际上它是一个天蓝色的队列,因此它是跨网间的HTTP调用) ]。
我们的问题是,记录任何信息(3个区域中的任何一个)的行为会使服务请求线程太长而无法写入所有日志接收器100次。我们已经测量了请求处理时间花费在记录接收器上的时间的四分之三。所以,你可以看到我们需要显着优化!
我们想加快速度,并从日志写入中释放请求线程。我们希望使用另一个线程在后台按自己的步调将日志记录数据写入3个日志记录存储区。所以我们认为将日志记录排队写入内存队列中,以便日志写入线程可以并行处理它们并发出多个请求,这是一条路。
Stephen Cleary的书“C#Cookbook中的并发”(fab参考)指出,在这种情况下使用像BlockingCollection<T>
这样的阻塞集合是理想的。因此,一次一个线程可以生成数据(并写入内存队列),另一个线程可以使用内存队列中的数据。似乎这对我们的情况是理想的。然而,在我们的例子中,因为我们运行在ASP.NET主机中,并且线程池线程对于Web服务器非常宝贵(为了可伸缩性),我们只希望有一个线程专用于[消费]全部3个日志队列。让所有其他线程处理入站Web请求,并[生成]记录数据。
所以问题变为:如何使用的BlockingCollection<T>
3个实例(每个类型的日志记录),并支持:
- 任何用于产生数据的生产者[呼入web请求线程]的
- 一个单独的(专用)日志线程使用者,可以持续有效地使用所有三个队列。
任何人都可以想到一个设计模式,可以在这里工作吗?对我们来说缺少的一件事是消费者如何有效地清空所有三个队列,而不会阻塞任何队列,并且不断处理所有三个队列。
你可以有一个'BlockingCollection'其中'T'是一些自定义的类,可以包含任何三种类型。您可以在此类型中使用枚举来检测此类真正拥有哪种类型。 –
谢谢,但我没有看到你的回答,我们如何处理所有三个'BlockingCollection'队列与同一个消费者线程,连续不等待任何一个队列。 –
我建议你有一个'BlockingCollection',而不是三个。 –