2

我有一个在 IIS6 或 7 上运行的 ISAPI 过滤器。当有多个工作进程(“Web garden”)时,过滤器将被加载并在每个 w3wp.exe 中运行。

如何有效地允许过滤器将其活动记录在单个合并日志文件中?

  • 来自不同(并发)进程的日志消息不得相互干扰。换句话说,从任何 w3wp.exe 发出的单个日志消息必须在日志文件中实现为单个连续行。

  • 日志文件的争用应该最小。这些网站每秒可以处理 100 个请求。

  • 严格的时间顺序是首选。换句话说,如果 w3wp.exe 进程 #1 在 t1 发出消息,然后进程 #2 在 t2 发出消息,然后进程 #1 在 t3 发出消息,则消息应该以正确的时间顺序出现在日志文件中。

我目前的方法是每个进程都拥有一个单独的日志文件。这有明显的缺点。

一些想法:

  • 指定 w3wp.exe 之一为“日志文件所有者”,并通过该特殊进程发送所有日志消息。这在工作进程回收的情况下存在问题。

  • 使用操作系统互斥锁来保护对日志文件的访问。这足够高性能吗?在这种情况下,每个 w3wp.exe 在同一个文件系统文件上都有一个 FILE。每次写入后我必须刷新日志文件吗?这行得通吗?

有什么建议么?

4

7 回答 7

2

一开始我想说我最喜欢你目前的方法,因为每个进程都不共享任何东西,然后我意识到,嗯,它们可能都在下面共享同一个硬盘驱动器。因此,仍然存在发生争用的瓶颈。或者操作系统和硬盘控制器在处理这个问题上真的很聪明?

我认为您要做的是让日志的写入不会减慢正在执行实际工作的线程。

因此,在同一台机器上运行另一个进程(较低优先级?),它实际上将日志消息写入磁盘。不使用建议的 UDP 与其他进程通信,而是使用进程共享的内存。令人困惑的是,也称为内存映射文件。有关内存映射文件的更多信息。在我的公司,我们发现内存映射文件比环回 TCP/IP 在同一个盒子上的通信要快得多,所以我假设它也比 UDP 快。

对于初学者来说,您在共享内存中实际拥有的可能是一个 std::queue,其中使用互斥锁保护推送和弹出。您的 ISAPI 线程将抓取互斥体以将内容放入队列中。日志记录过程将获取互斥体以将事物从队列中拉出,释放互斥体,然后将条目写入磁盘。互斥体只保护共享内存的更新,而不是文件的更新,因此理论上互斥体将被保留更短的时间,从而减少瓶颈。

日志记录过程甚至可以重新安排它正在写入的顺序,以便按顺序获取时间戳。

这是另一种变体:继续为每个进程拥有一个单独的日志,但在每个进程中都有一个记录器线程,这样主时间关键线程就不必等待记录发生以继续其工作。

我在这里写的所有内容的问题在于,整个系统——硬件、操作系统、多核 CPU L1/L2 缓存的工作方式、你的软件——太复杂了,无法通过简单的思考来轻松预测。编写一些简单的概念验证应用程序,用一些时间安排它们,然后在真实硬件上试用它们。

于 2009-10-17T00:31:46.477 回答
1

在这里记录到数据库有意义吗?

于 2009-10-02T19:10:27.117 回答
1

我过去使用过基于 UDP 的日志记录系统,我对这种解决方案很满意。

日志通过 UDP 发送到日志收集器进程,该进程负责定期将其保存到文件中。

我不知道它是否可以在您的高性能环境中工作,但我对在压力较小的应用程序中的解决方案感到满意。

我希望它有所帮助。

于 2009-10-14T19:42:32.790 回答
0

您可以使用带有 LockFile() 和 UnlockFile() 的 Win32 文件锁定机制,而不是使用 OS Mutex 来控制对文件的访问。

于 2009-10-16T21:37:28.327 回答
0

我的建议是将消息异步(UDP)发送到负责记录日志的进程。
该过程将:
- 一个线程接收器将消息放入队列;
- 一个线程负责从队列中删除消息,放入时间排序列表中;
- 列表中只有一个线程监控消息,并且只有时间长度大于最小值的消息才应保存在文件中(以防止延迟消息被无序写入)。

于 2009-10-17T01:13:29.667 回答
0

您可以继续记录到单独的文件并查找/编写工具以稍后合并它们(可能是自动化的,或者您可以在要使用文件的时候运行它。)

于 2009-10-17T01:15:58.120 回答
0

Windows Vista 及更高版本中包含的 Windows事件跟踪为此提供了很好的功能。

摘抄:

Windows 事件跟踪 (ETW) 是一种高效的内核级跟踪工具,可让您将内核或应用程序定义的事件记录到日志文件中。您可以实时或从日志文件中使用事件,并使用它们来调试应用程序或确定应用程序中出现性能问题的位置。

于 2010-01-20T17:00:09.333 回答