windows - 在 ISAPI 过滤器中,对于多个进程的通用日志文件来说,什么是好方法?

标签 windows logging mutex isapi w3wp.exe

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

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

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

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

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

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

一些想法:

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

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

有什么建议吗?

最佳答案

起初我想说我最喜欢你当前的方法,因为每个进程不共享任何东西,然后我意识到,好吧,它们可能都在下面共享相同的硬盘驱动器。因此,仍然存在发生争用的瓶颈。或者也许操作系统和硬盘 Controller 真的很聪明地处理这个问题?

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

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

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

日志记录进程甚至可以重新排列其写入内容的顺序,以按顺序获取时间戳。

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

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

关于windows - 在 ISAPI 过滤器中,对于多个进程的通用日志文件来说,什么是好方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1511290/

相关文章:

python - 检查 Flask 请求上下文是否可用

java - 何时在系统输出上使用 log4j

mutex - 如何使方法不需要锁定互斥锁的可变自身?

c++ - 如何同步三个线程?

windows - docker : Hyper-V was unable to find a virtual switch with name "DockerNAT"

windows - SMTP VRFY 扫描器的用途是什么?

azure - 如何在 Application Insights 中查看日志?

c++ - 共享 vector 与原子 bool 同步

java - 需要一致的javac和java

windows - Grep ffmpeg 时间/持续时间以获取进度流?