使用Java写文件到Google Cloud Storage后不删除临时文件



我使用Hadoop GCS Connector 3-2.2.2和Google - Cloud - Storage version 1.113.14在Google Cloud Storage上写入数据。

我有一个文件类,它有一个写方法,它返回一个OutputStream如下使用hadoop类:

protected FileSystem fs;
protected Path path;
public File(String path) {
this.path = new Path(path);
Configuration conf = new Configuration();
conf.set("fs.defaultFS", fsURL);
conf.setBoolean("dfs.support.append", true);
conf.setInt("ipc.client.connect.max.retries.on.timeouts", 2);
this.fs = FileSystem.newInstance(conf);
}
@Override
public OutputStream write(boolean overwriteIfExists) throws IOException {
return fs.create(path, overwriteIfExists);
}

fs是org.apache.hadoop.fs.FileSystem的实例;

我甚至尝试使用谷歌云存储sdk来实现我的写方法:

@Override
public OutputStream write(boolean overwriteIfExists, boolean create) throws IOException {
if (!overwriteIfExists && exists()) {
throw new IOException("File already exists");
}
if (overwriteIfExists && exists()) {
delete();
} // If will write it will mean a new file
BlobId blobId = BlobId.of(bucketName, objectName);
BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();

WriteChannel writeChannel = storage.writer(blobInfo);
writeChannel.setChunkSize(64 * 1024 * 1024);
return Channels.newOutputStream(writeChannel);
}

应用程序的其他部分可以创建File类的实例并写入OutputStream,下面是如何测试/模拟写入的示例:

public void write() {
try {
File file = File.newInstance("dir/someFileName");
try (DataOutputStream os = new DataOutputStream(new BufferedOutputStream(file.write(true), this.bufferSize))) {
long i;
for (i = 0L; i < 4096; i++) {
os.write(String.format("some arbitrary string %dn", new Object[] { Long.valueOf(i) }).getBytes());
} 
} catch (Throwable t) {
System.out.println("Couldn't write file");
} 
} catch (IOException e) {
System.out.println("Couldn't write file");
} 

}

写入后,当我使用gsutil ls dir/检查写入文件时,我希望找到我刚刚创建的文件,但我得到2个额外的临时文件(具有GCS_SYNCABLE_TEMPFILE前缀),应该被删除

gs://dir/_gcs_syncable_tempfile_somefilename.txt.0.24fccb78 - 8 cea - 45 - fd - 852 d ed9385e4246bg://dir/_gcs_syncable_tempfile_somefilename.txt.0.cf132710 - 9 d71 - 4939 - a5d8 - 02 - b0279cdf3cg://dir/someFileName.txt

是否有一些配置我需要做或为什么这些临时文件没有被删除?

或者这可能是在任何相关的jar中不兼容?我正在使用以下版本的谷歌相关的依赖:

  • 组:"表示。hadoop',名称:'hadoop-common',版本:'3.2.0'
  • 组:"表示。hadoop',名称:'hadoop-hdfs',版本:'3.2.0'
  • 组:"表示。hadoop',名称:'hadoop-hdfs-client',版本:'3.2.0'
  • 组:"com.google.cloud。Bigdataoss ',名称:' gcs-connector ',版本:"hadoop3-2.2.2">
  • 组:"com.google。api-client’,名字:' google-api-client ', version: ' 1.31.3 '
  • 组:"com.google.cloud",名称:' google-cloud-core ',版本:' 1.93.4 '
  • 组:"com.google。
  • , name: ' google-cloud-core-http ', version: ' 1.93.4 '
  • 组:"com.google。Cloud ',名称:' google-cloud-storage ',版本:"1.106.0">
  • 组:"com.google。http客户端",名称:' google-http-client ', version: ' 1.38.0 '
  • 组:"com.google。"google-http-client-jackson2"版本:"1.38.0">
  • OutputStream的源代码是公开的这个GitHub链接
  • TEMP文件的行为是客户端库的属性直接GCS。
  • 附加的文档链接提供了详细信息,但一般概述为:

在第一个hsync()、sync()或close()调用之前,该通道的行为将与基本的非同步通道相同,直接写入目标文件。在第一次调用hsync()/sync()时,目标文件被提交,并使用隐藏文件前缀(下划线)创建一个新的临时文件,该后缀在该系列中的每个后续临时文件中都不同;在此期间,读取器可以读取提交给目标文件的数据,但不能读取自上次hsync()调用以来写入临时文件的字节。在随后的每次hsync()/sync()调用中,临时文件关闭(),组成目标文件,然后删除,并在新的文件名下打开一个新的临时文件以供进一步写入。注意:每个hsync()/sync()都需要许多底层的读取和突变请求顺序发生,因此延迟预计会相当高。

如果在过程中出现错误,可能有一个或多个临时文件无法清理,需要人工干预来发现和删除任何此类未使用的文件。在这种情况下,在最近一次成功的hsync()之前写入的数据是持久的和安全的。

文件未被关闭的可能原因是您没有关闭代码库中的流或存在错误。一步步调试代码,检查流是否被正确关闭,文件是否被删除,如下所示

注意:由于代码是异步的,您需要确保执行删除的线程正在运行。