Webapp,在我的项目中,根据最终用户的搜索提供下载CSV文件功能,正在执行以下操作:
打开一个文件" download.csv" (不使用File.createTempFile(String prefix, 字符串后缀,文件目录);但始终只是" download.csv"),从Sql记录集向其写入数据行,然后使用FileUtils将该文件的内容复制到servlet的OutputStream。
记录集基于搜索条件,例如1月1日至3月30日。
这是否会导致一个潜在的情况,即文件包含2个用户的内容,这些用户使用不同的日期范围/其他过滤器并同时提交以便JVM同时处理请求?
目前我们处于开发阶段且数据非常少。
我知道我们可以编写自动化测试来测试这个,但想知道这个理论。
我建议使用Http Response的OutputStream(将其作为vanilla OutputSteam传递给服务层,然后直接写入或包装在Buffered Writer中,然后写入它)。
唯一的缺点是数据写入速度比文件副本慢。 好像记录集中有更多数据需要时间来迭代它。但是请求的总时间应该更少? (因为写入文件输出流的时间与从文件复制到servlet输出流的时间相同+时间。)
是否有人围绕此进行测试,并提供测试案例或解决方案进行分享?
答案 0 :(得分:1)
如果你真的想进入两个部分的深度,这是一个棘手的问题。
<强> 并发 强>
正如你所写的那样,如果你正在研究一个多线程系统(现在几乎所有系统都是这样的系统),这个“同名”的东西可能会导致race condition。我已经看到一些像这样的编码,它可能会导致很多麻烦。结果文件不仅可以包含来自两个搜索的行,还可以包含合并后的字符。
<强>示例:强>
Thread 1 wants to write: 123456789\n
Thread 2 wants to write: abcdefghi\n
产出可能会有所不同:
第一种情况:
123456789
abcdefghi
第二种情况:
1234abcd56789
efghi
我肯定会使用至少唯一的(UUID.randomUUID()
)名称来“解决”这个问题。
<强> 并发 强>
如果深入了解,拥有磁盘IO是一件棘手的事情。 spead可以在视频范围内变化。在JVM中,您也可以拥有blocking
和non-blocking
IO。阻塞的人可能要等到数据确实在磁盘上,而另一个人会做一些“魔术”以便稍后刷新文件。在here.
TL.DR。: 根据经验,最好将内容放入内存中(如果适合)并且不要打扰磁盘。如果为此目的使用线程内存,也可以避免并发问题。因此,在您的情况下,重写给定的部分以仅利用内存并写入输出可能会更好。