通过网络读取和解析大型文本文件的最佳方法是什么?
我有一个问题,要求我从远程计算机解析多个日志文件。
有一些并发症:
1)该文件可能正在使用中
2)文件可能会很大(100mb +)
3)每个条目可以是多行
要解决使用中的问题,我需要先复制它。我目前正在将其直接从远程计算机复制到本地计算机,然后在此处进行解析。这就导致了问题2. 由于文件很大,因此在本地复制可能会花费一些时间。
为了延长解析时间,我想使解析器成为多线程,但这使得处理多行条目变得有些棘手。
两个主要问题是:
1)我如何加快文件传输速度(压缩?,是否还需要本地传输?,我可以通过其他方式读取正在使用的文件吗?)
2)在线程之间拆分行时如何处理多行条目?
更新:之所以没有对服务器进行明显的解析,是因为我希望对cpu的影响尽可能小。我不想影响系统即时测试的性能。
解决方案
如果要读取顺序文件,则要通过网络逐行读取。我们需要一种能够流式传输的传输方法。我们需要检查IO流技术以解决此问题。
像这样的大型IO操作不会从多线程中受益,因为我们可以像通过网络读取它们一样快地处理它们。
我们另一个不错的选择是将日志解析器放在服务器上,然后下载结果。
考虑我们已经复制文件的最简单方法是在复制之前对其进行压缩,并在复制完成后进行解压缩。压缩文本文件将获得巨大收益,因为zip算法通常可以很好地对其进行处理。而且,我们现有的解析逻辑也可以保持不变,而不必将其连接到远程网络文本阅读器。
此方法的缺点是我们将无法非常有效地逐行更新,这对于日志解析器来说是一件好事。
在通过Internet传输大文件之前,我曾使用SharpZipLib对其进行压缩。所以这是一种选择。
1)的另一个想法是创建一个在远程计算机上运行并在该计算机上进行解析的程序集。我们可以使用.NET远程处理从本地计算机访问程序集。远程程序集将需要是Windows服务或者托管在IIS中。这样一来,我们就可以将日志文件的副本保留在同一台计算机上,并且从理论上讲,处理它们所花的时间会更少。
我认为使用压缩(deflate / gzip)将有所帮助
我猜这取决于它的"远程"程度。 100Mb LAN上的100MB大约需要8秒钟的时间...达到千兆位,我们将在1秒钟左右获得它。卡的价格是50美元* 2,而交换机的价格是100美元,这是我们可以做的非常便宜的升级。
但是,假设它比那更远,我们应该能够以只读模式将其打开(因为在复制时正在读取它)。 SMB / CIFS支持文件块读取,因此我们应该在此时传输文件(当然,我们实际上并没有说出如何访问文件,我只是假设SMB)。
多线程将无济于事,因为无论如何我们都将受到磁盘或者网络的限制。
使用压缩进行传输。
如果解析确实使我们放慢了速度,并且我们有多个处理器,则可以拆分解析工作,只需以一种聪明的方式完成它-拥有确定性算法,由工人负责处理不完整的记录。假设我们可以确定某行是记录中间的一部分,例如,我们可以将文件分成N / M个段,每个段负责M行。当其中一个作业确定其记录尚未完成时,它只需继续读取,直到到达记录的末尾。当其中一个作业确定它正在读取没有开头的记录时,应跳过该记录。
从性能的角度来看,更好的选择是在远程服务器上执行解析。除了特殊情况外,网络速度始终是瓶颈,因此限制通过网络发送的数据量将极大地提高性能。
这是许多数据库使用在服务器端运行的存储过程的原因之一。
通过使用多线程来提高解析速度(如果有的话)将被网络传输的相对速度所淹没。
如果我们承诺在解析文件之前传输文件,则可以考虑的一种选择是在进行文件传输时使用动态压缩。
例如,有可用的sftp服务器可即时执行压缩。
在本地端,我们可以使用libcurl之类的东西来进行传输的客户端,它也支持即时解压缩。
如果可以复制文件,则可以阅读。因此,无需首先复制它。
编辑:使用FileStream类可以更好地控制访问和共享模式。
new FileStream("logfile", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
应该做到的。