Java Google数据流批处理文件性能差

Java Google数据流批处理文件性能差,java,performance,file-io,google-cloud-dataflow,apache-beam-io,Java,Performance,File Io,Google Cloud Dataflow,Apache Beam Io,我正在尝试使用ApacheBeam2.16.0构建一个管道来处理大量XML文件。平均计数为每24小时7000万次,在峰值负载下可高达5亿次。 文件大小从~1KB到200KB不等(有时甚至更大,例如30MB) 文件经过各种转换,最终目的地是BigQuery表,以便进一步分析。所以,首先我读取xml文件,然后反序列化为POJO(在Jackson的帮助下),然后应用所有必需的转换。转换运行得非常快,在我的机器上,根据文件大小,我每秒可以得到大约40000个转换 我主要关心的是文件读取速度。我觉得所有的

我正在尝试使用ApacheBeam2.16.0构建一个管道来处理大量XML文件。平均计数为每24小时7000万次,在峰值负载下可高达5亿次。 文件大小从~1KB到200KB不等(有时甚至更大,例如30MB)

文件经过各种转换,最终目的地是BigQuery表,以便进一步分析。所以,首先我读取xml文件,然后反序列化为POJO(在Jackson的帮助下),然后应用所有必需的转换。转换运行得非常快,在我的机器上,根据文件大小,我每秒可以得到大约40000个转换

我主要关心的是文件读取速度。我觉得所有的阅读都是通过一个工人来完成的,我不明白这是如何并行的。我在10k测试文件数据集上进行了测试

在我的本地机器(MacBook pro 2018:ssd、16 gb ram和6核i7 cpu)上的批处理作业可以每秒解析大约750个文件。如果我使用n1-standard-4机器在数据流上运行这个,我每秒只能得到大约75个文件。它通常不会放大,但即使放大(有时多达15个工作人员),我也只能每秒获得大约350个文件

更有趣的是流媒体工作。它立即从6-7个worker开始,在UI上我可以看到1200-1500个元素/秒,但通常不会显示速度,如果我选择页面上的最后一项,它显示它已经处理了10000个元素

批处理作业和流作业之间的唯一区别是FileIO的此选项:

。连续(持续时间.standardSeconds(10),Watch.Growth.never())

为什么这会在处理速度上产生如此大的差异

运行参数:

--runner=DataflowRunner
--project=<...>
--inputFilePattern=gs://java/log_entry/*.xml
--workerMachineType=n1-standard-4
--tempLocation=gs://java/temp
--maxNumWorkers=100
xml文件的示例:

<LogEntry><EntryId>0</EntryId>
    <LogValue>Test</LogValue>
    <LogTime>12-12-2019</LogTime>
    <LogProperty>1</LogProperty>
    <LogProperty>2</LogProperty>
    <LogProperty>3</LogProperty>
    <LogProperty>4</LogProperty>
    <LogProperty>5</LogProperty>
</LogEntry>
0
试验
12-12-2019
1.
2.
3.
4.
5.
现实生活中的文件和项目要复杂得多,有大量嵌套节点和大量转换规则

GitHub上的简化代码: 它只包含“瓶颈”部分—读取文件并反序列化为POJO


如果我能在我的机器上每秒处理750个文件(这是一个强大的工作程序),那么我希望在Dataflow中类似的10个工作程序上每秒处理7500个文件。

我试图编写一个带有一些功能的测试代码,以检查
FileIO.match
的行为和工作程序的数量[1]

在这段代码中,我将numWorkers的值设置为50,但您可以设置所需的值。我所看到的是
FileIO.match
方法将找到与这些模式匹配的所有链接,但在此之后,您必须分别处理每个文件的内容

例如,在我的例子中,我创建了一个接收每个文件的方法,然后用“new_line(
\n
)”字符分割内容(但在这里,您可以根据需要处理它,它还取决于文件的类型,csv、xml等)

因此,我将每一行转换为BigQuery理解的
TableRow
,并分别返回每个值(
out.output(tab)
),这样,数据流将根据管道的工作负载处理不同工人中的行,例如3个不同工人中的3000行,每个工人有1000行

最后,由于这是一个批处理过程,Dataflow将等待处理所有行,然后将其插入BigQuery

我希望这个测试代码能帮助你完成你的测试


[1]

有趣。。。在批处理模式和流式处理模式下,包大小通常较大,但不确定这是否相关。你能试着利用它吗,它已经被擦掉了,但这只是为了检查一下:FileIO.match()和你的XmlToPojoDoFn()@RezaRokni之间的Reshuffle.viaramonkey()我没有注意到任何区别。但在测试过程中,我改变了读取操作:FileIO.Match->FileIO.ReadMatches->readfile as bytes->convert bytes to POJO。我还以批处理模式对我的生产代码和更大的数据集(144k和1m文件)进行了测试:在n1-standard-2上,我能够用17名工人每秒获得大约1000k文件。这是更好的,但我仍然没有接近850文件/秒,像在我的本地机器。需要做更多的测试。我用这种方法更新了github代码。顺便说一句,当您在本地机器上进行测试时,文件放在哪里?在本地磁盘上还是在云存储桶中?@RezaRokni locally(ssd)。我想知道我是否可以在云上实现类似的读取性能。我想,您的文件位于云存储中,它们将被拉到工作人员身上。我主要关心的是文件读取性能。这是管道中最慢的部分。因此,我想知道是否有可能加快这一进程。或者阅读大量的小文本文件是个坏主意?读一个或多个更大的文件更好吗?你的表现如何?我还看到,您使用的是csv文件,我的案例是xml,因此不能将其划分为不同的工作程序(我需要一次读取整个文件才能对其进行解析)最好从不同的文件读取,因为这样我猜您会强制在不同的工作程序中并行执行,例如对我来说,在这一部分中,我能够看到工作人员如何增加以读取所有文件,例如,我使用了一个包含10000个文件的存储桶,工作人员增加到69个,每个工作人员大约144个文件。我知道您正在使用XML,我使用csv是因为它更容易尝试复制行为。也许你可以试着指定工人的数量,看看这个数量是否会增加。让我知道这一变化。将文件压缩到存档+自定义阅读器帮助很大。比如100-1000倍。我不知怎么错过了你的答案:“如果你认为答案对你有帮助,请投上一票。”。
<LogEntry><EntryId>0</EntryId>
    <LogValue>Test</LogValue>
    <LogTime>12-12-2019</LogTime>
    <LogProperty>1</LogProperty>
    <LogProperty>2</LogProperty>
    <LogProperty>3</LogProperty>
    <LogProperty>4</LogProperty>
    <LogProperty>5</LogProperty>
</LogEntry>