在中跨流程边界高效地流式传输数据.NET
本文关键字:高效 传输 数据 NET 边界 程边界 | 更新日期: 2023-09-27 17:59:55
我已经断断续续地开发了一个内部开发工具好几个星期了,但我遇到了一个丑陋的绊脚石,我还没有找到一个好的解决方案。我希望有人能就使用现有框架的最佳方式提供一些想法或指导。NET。
背景:此工具的目的是将多种不同类型的日志文件(Windows事件日志、IIS、SQL跟踪等)加载到同一数据库表中,以便将它们一起进行排序和检查。我个人的目标是简化整个过程,这样我们就只进行一次传递,而不会将整个日志缓存在内存或磁盘中。当日志文件达到数百MB或GB范围时,这一点非常重要。快速性能是好的,但缓慢而不引人注目(允许您同时处理其他事情)比运行速度更快但在此过程中垄断系统要好,所以我专注于最大限度地减少RAM和磁盘使用。
到目前为止,我已经迭代了一些不同的设计,试图将其归结为简单的设计。我希望日志解析器的核心——必须与任何外部库或文件交互才能真正读取数据的部分——尽可能简单,并符合标准接口,这样添加对新格式的支持就尽可能容易。目前,解析方法返回一个IEnumerable<Item>
,其中Item
是一个自定义结构,我使用yield return
来最小化缓冲量。
然而,我们很快就遇到了一些丑陋的限制:用于处理这些文件格式的库(通常由Microsoft提供)。最大也是最丑陋的问题是:其中一个库只能在64位中工作。另一个(适用于SSMS日志的Microsoft.SqlServer.Management.Trace TraceFile)只能在32位中工作。众所周知,32位和64位的代码不能混用。由于本练习的全部目的是拥有一个可以处理任何格式的实用程序,因此我们需要有一个单独的子进程(在本例中,它处理仅32位的部分)。
最终的结果是,我需要64位的主进程来启动一个32位的子进程,为它提供解析日志文件所需的信息,并以某种不需要将整个内容缓冲到内存或磁盘的方式将数据流式传输回来。起初,我尝试使用stdout,但由于数据量太大,结果失败了。我尝试过使用WCF,但它实际上并不是为了处理作为"客户端"的子级的"服务",而且很难从它们想要的工作方式向后同步,而且我不知道我是否真的能让它们正确地流式传输数据。我不想使用打开不安全网络端口的机制,或者如果有人运行多个实例,可能会意外发生串扰的机制(我希望这种情况能正常工作——每个64位主进程都会生成并运行自己的子进程)。理想情况下,我希望运行在32位子级中的解析器的核心看起来与运行在64位父级中的语法分析器的核心相同,但我不知道是否可以继续使用yield return
,即使有一些包装器来帮助管理IPC。中是否有任何现有框架。NET让这相对容易吗?
WCF确实有P2P模式,但如果所有进程都是本地机器,则最好使用IPC,如命名管道,因为后者运行在内核模式中,并且没有前者的消息开销。
如果失败,您可以尝试COM,它在32和64位进程之间的通信应该不会有问题-告诉我更多
如果有人偶然发现这一点,我将发布我们最终确定的解决方案。关键是将进程间WCF服务接口重新定义为不同于进程内IEnumerable
接口。我们没有尝试跨进程边界yield return
,而是在其间插入了一个使用枚举器的代理层,这样我们就可以反复调用"给我一个项"方法。这可能比真正的流式处理解决方案有更多的性能开销,因为每个项目都有一个方法调用,但它似乎确实完成了任务,而且不会泄漏或消耗内存。
我们确实遵循了Micky关于使用命名管道的建议,但仍然在WCF中。我们还使用命名信号量来协调这两个进程,因此在"子服务"完成启动之前,我们不会尝试进行服务调用。