"java.io.FileNotFoundException: No files matched spec" thought文件已成功写入

"java.io.FileNotFoundException: No files matched spec" althought file is successfully written to

Edit -- the error seems to come not from the write block but from the output block, which is even stranger. Modified to reflect my investigations.

Edit2 -- solved - the issue is due to an improperly closed writer, for some reason only triggered in the DataflowRunner but not in the DirectRunner. Will add an answer later today when I find the time. If anyone has an insight on why the writer is closed in the DirectRunner but not in the DataflowRunner, I am very interested.


考虑以下 Java 2.5.0 数据流代码:

BlobId blobTranscriptId = BlobId.of(tempBucket, fileName);
BlobInfo blobTranscriptInfo = BlobInfo.newBuilder(blobTranscriptId).build();
try (WriteChannel writer = storageClient.writer(blobTranscriptInfo)) {
    LOG.info("Writing file");
    writer.write(ByteBuffer.wrap(currentString.toString().getBytes(UTF_8)));
    processContext.output("gs://" + tempBucket + "/" + fileName)
    LOG.info("Wrote " + fileName);
} catch (Exception e) {
    LOG.warn("Error caught while writing content : " + ExceptionUtils.getStackTrace(e));
}

当 运行 在本地(在 DirectPipeline 中)时,此代码工作正常且没有错误。

然而,当 运行 在 Dataflow 中(在 DataflowRunner 中)时,我们注意到一个奇怪的行为:

在 google gcp“没有文件匹配规范” 上搜索没有 return 一个结果。查看 org.apache.beam.sdk.io.FileSystems.java 中的源代码(在第 173 行声明的错误)并没有多大帮助。

使用调试器执行后显示使用 DirectRunner,代码 从未调用 FileIO.MatchAll,这是错误的来源。但是,对于 DataflowRunner,错误会以某种方式触发。没有理由将输出字符串解释为文件路径,因为堆栈跟踪表明错误发生在这个阶段,它被声明为输出 PCollection<String>.

为什么 FileNotFoundException 即使文件显然已创建且内容正确,但仍会启动?


一些可能有帮助的附加信息:


补充调查:

更详细地查看堆栈跟踪显示错误通过 FileIO 发生,它本身通过此错误之后的 TextIO 阶段调用。

发生的事情是,在我上面的代码中,我没有在 将字符串输出到 TextIO 之前关闭编写器 writer.close() ,而是 after(通过 try(Writer writer){} 块)。由于桶在其编写器关闭之前不会注册文件,因此 TextIO 无法找到文件并启动 FileNotFoundException。这反过来会关闭 try 块并启动 writer.close(),这就是文件最终仍出现在存储桶中的原因。

出于某种我不知道的原因,通过本地 DirectLauncher 启动时不会发生这种情况。