0

您好,如果问题描述听起来奇怪且不准确,首先很抱歉。用英语描述我的复杂问题对我来说并不容易,但我希望你能理解我的意思。

我制作了一个用于解析 Web 服务器访问日志的 CLI 工具。我专注于性能和使用的灵活性。

因此,我使用 MMap 将 LogFiles 读入内存,然后将内存映射的 char* 传递给并行 OpenMP 处理循环。

在 omp 并行 for 循环中,我只使用 boost::regex_search 解析每个 LogString 中的几个信息子字符串,并将事件数据存储在线程本地自定义 LogEvent 类型对象中。

从当前字符串创建此 LogEvent-Object 后,我​​将 LogEvent 附加到向量并继续解析下一个字符串,依此类推。

棘手的是我在程序启动时解析了一个用户配置文件。用户可以通过指定与数据匹配的字段名称和正则表达式来定义多个“数据字段”。

例如:

Time = \d{2}\/\w{3}\/\d{4}
IP = \d{1,3}\.\d{1,3}.\d{1,3}.\d{1,3}
Object = \d{2,8}\_w\d{1,3}.mp4|\d{2,10}.flv

此外,用户可以指定生成输出报告数据的顺序

例如:

field_0 = %IP%
field_1 = %Object%
field_2 = %Time%

输出字符串可能如下所示:

10.20.30.1;video_xyz.flv;Jul/23/2011:11:12;3 
10.20.30.1;video_xyz.flv;Jul/23/2011:11:17;1 
10.20.30.1;video_xyz.flv;Jul/23/2011:11:18;12
10.11.30.1;video_xyz.blabla.mp4;Jul/23/2011:11:12;3  

我遇到的问题是,流式传输视频文件会导致日志中出现多个访问事件。我无法真正识别出只是重新加载/缓冲流的人,因为不同的客户端平台在生成服务器响应代码时具有不同的行为。

现在我多次计算事件,这通常是错误的。

我该如何处理这个问题?我知道这很笼统,但是如果您考虑一下我的程序以及我如何描述它,您很快就会发现这个问题很难用我的程序设计来解决。

我找到了一种或另一种解决方法,但它总是对性能产生非常糟糕的影响,而不是合法的解决方案。

不知何故,我必须避免在解析时将这些 LogEvents 附加到 LogEvent-Objects 的向量中,因为在那之前,字符串仍处于正确的时间顺序,因此我可以将当​​前字符串与前一个字符串进行比较,依此类推。

在那之后,omp 关键阶段开始,线程本地结果被合并,如果我想检查错误的多次命中计数,我将不得不搜索整个数据数组,即 nogo。

我希望我的问题足够清楚。有任何想法吗?(不知道示例代码是否会有所帮助,因为我认为这更像是一个设计问题)......

4

1 回答 1

0

好的,最后我找到了一个可以忍受一段时间的解决方法。

在解析字符串时,我现在总是从每个日志字符串中获取 IP 地址和目标项。

我有一个线程本地映射,将 IP 地址存储为键,将目标项目(例如视频流)存储为值。

每当我想计算我之前检查的日志事件时,如果当前处理的 LogsStrings 的 IP 地址已经是我的线程本地映射的键。

如果不是,则可以安全地计算事件。我将当前 IP 添加为键,将对象添加为值,这意味着我更新了此特定 IP 的最后访问对象。

如果它已经是我的地图的一个键,我检查这个键的值(目标项)是否与我当前的 LogStrings 目标相同。

如果是这样,那可能意味着该用户最后一次访问我服务器上的任何内容是在访问同一视频流时。

当对象发生变化时,我只会继续计算来自该 IP 地址的事件。

因为用户不太可能从一个流切换到另一个流然后再返回(即使他认为计算它是正确的)所以看起来我们在这里得到了一个新事件,我们真的想计算它。

这有点像反向灰名单。任何 ip 只计算一次,然后阻止计算,直到由于新对象而生成新签名。

当然这也是对性能的影响,所以如果您有更好的想法,请随时回答:P

于 2011-08-29T09:57:29.747 回答