Amazon s3 AmazonS3:获取警告:S3AbortableInputStream:没有从S3ObjectInputStream读取所有字节,正在中止HTTP连接
以下是我得到的警告: S3AbortableInputStream:并非所有字节都从S3ObjectInputStream读取,正在中止HTTP连接。这可能是一个错误,并可能导致次优行为。使用后,通过远程获取或清空输入流,仅请求所需的字节 我尝试使用try with resources,但S3ObjectInputStream似乎无法通过此方法关闭Amazon s3 AmazonS3:获取警告:S3AbortableInputStream:没有从S3ObjectInputStream读取所有字节,正在中止HTTP连接,amazon-s3,aws-sdk,aws-java-sdk,Amazon S3,Aws Sdk,Aws Java Sdk,以下是我得到的警告: S3AbortableInputStream:并非所有字节都从S3ObjectInputStream读取,正在中止HTTP连接。这可能是一个错误,并可能导致次优行为。使用后,通过远程获取或清空输入流,仅请求所需的字节 我尝试使用try with resources,但S3ObjectInputStream似乎无法通过此方法关闭 try (S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket,
try (S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket, key));
S3ObjectInputStream s3ObjectInputStream = s3object.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(s3ObjectInputStream, StandardCharsets.UTF_8));
){
//some code here blah blah blah
}
我还尝试了以下代码并显式关闭,但也不起作用:
S3Object s3object = s3Client.getObject(new GetObjectRequest(bucket, key));
S3ObjectInputStream s3ObjectInputStream = s3object.getObjectContent();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(s3ObjectInputStream, StandardCharsets.UTF_8));
){
//some code here blah blah
s3ObjectInputStream.close();
s3object.close();
}
任何帮助都将不胜感激
PS:我只从S3中读取了两行文件,该文件包含更多数据。通过其他媒体获得了答案。在这里分享: 警告表示您调用close()时没有读取整个文件。这是有问题的,因为S3仍在尝试发送数据,而您将使连接处于一种糟糕的状态 这里有两个选项:
为了给Chirag Sejpal的答案添加一个示例(详细说明选项1),可以使用以下内容在关闭输入流之前从输入流读取其余数据:
S3Object S3Object=s3Client.getObject(新的GetObjectRequest(bucket,key));
尝试(S3ObjectInputStream S3ObjectInputStream=s3object.getObjectContent()){
试一试{
//根据需要从流中读取
}捕获(例外e){
//根据需要处理异常
}最后{
while(s3ObjectInputStream!=null&&s3ObjectInputStream.read()!=-1){
//阅读流的其余部分
}
}
//try with resources语句将自动关闭流
}
我遇到了同样的错误
正如其他人指出的,lambda中的/tmp空间被限制为512 MB。
如果lambda上下文被重新用于新的调用,那么/tmp空间已经满了一半
因此,当读取S3对象并将所有文件写入/tmp目录时(正如我所做的那样),
我在两者之间的某个地方用完了磁盘空间。
Lambda退出时出错,但并不是从S3ObjectInputStream读取所有字节
TransferManager transferManagerClient = TransferManagerBuilder.standard()
.withS3Client(amazonS3Client)
.build();
因此,我们需要记住两件事:
1) 如果第一次执行导致了问题,请谨慎使用/tmp空间。
我们只有512MB
2) 如果第二次执行导致问题,那么可以通过攻击根问题来解决。
无法删除/tmp文件夹。
因此,在执行完成后删除/tmp文件夹中的所有文件
在java中,我所做的就是成功地解决了这个问题
publicstringhandlerequest(映射keyValuePairs,Context lambdaContext){
试一试{
//都在这里工作
}捕获(例外e){
error(“error{}”,例如toString());
返回“错误”;
}最后{
deleteAllFilesInTmpDir();
}
}
私有void deleteAllFilesInTmpDir(){
Path Path=java.nio.file.Path.get(file.separator,“tmp”,file.separator);
试一试{
if(Files.exists(path)){
deleteDir(path.toFile());
info(“已成功清除tmp目录”);
}
}捕获(例外情况除外){
logger.error(“无法清理tmp目录”);
}
}
公共无效删除目录(文件目录){
File[]files=dir.listFiles();
如果(文件!=null){
用于(最终文件:文件){
deleteDir(文件);
}
}
dir.delete();
}
我遇到了同样的问题,下面的课程帮助了我
@Data
@AllArgsConstructor
public class S3ObjectClosable implements Closeable {
private final S3Object s3Object;
@Override
public void close() throws IOException {
s3Object.getObjectContent().abort();
s3Object.close();
}
}
现在,您可以在没有警告的情况下使用
try (final var s3ObjectClosable = new S3ObjectClosable(s3Client.getObject(bucket, key))) {
//same code
}
以下是Chirag Sejpal回答中的选项#1,我使用以下语句排出S3AbortableInputStream,以确保连接可以重用:
com.amazonaws.util.IOUtils.drainInputStream(s3ObjectInputStream);
这是我的解决方案。我使用的是SpringBoot2.4.3 创建一个亚马逊s3客户端
AmazonS3 amazonS3Client = AmazonS3ClientBuilder
.standard()
.withRegion("your-region")
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials("your-access-key", "your-secret-access-key")))
.build();
// Note that in this line the s3 file downloaded has been transferred in to the temporary file that we created
Download download = transferManagerClient.download(
new GetObjectRequest("your-s3-bucket-name", "your-s3-key"), file);
// This line blocks the thread until the download is finished
download.waitForCompletion();
创建一个亚马逊传输客户端
TransferManager transferManagerClient = TransferManagerBuilder.standard()
.withS3Client(amazonS3Client)
.build();
在/tmp/{your-s3-key}中创建一个临时文件,以便我们可以将下载的文件放入该文件中
File file = new File(System.getProperty("java.io.tmpdir"), "your-s3-key");
try {
file.createNewFile(); // Create temporary file
} catch (IOException e) {
e.printStackTrace();
}
file.mkdirs(); // Create the directory of the temporary file
然后,我们使用transfer manager客户端从s3下载文件
AmazonS3 amazonS3Client = AmazonS3ClientBuilder
.standard()
.withRegion("your-region")
.withCredentials(
new AWSStaticCredentialsProvider(
new BasicAWSCredentials("your-access-key", "your-secret-access-key")))
.build();
// Note that in this line the s3 file downloaded has been transferred in to the temporary file that we created
Download download = transferManagerClient.download(
new GetObjectRequest("your-s3-bucket-name", "your-s3-key"), file);
// This line blocks the thread until the download is finished
download.waitForCompletion();
现在,s3文件已成功传输到我们创建的临时文件中。我们可以获取临时文件的输入流
因为临时文件不再需要了,我们只是删除它
file.delete();
“连接可以重用”是什么意思?我认为每个S3 GET-requestHi-Chirag都会创建一个HTTP连接,您能详细说明一下第1点吗(从输入流读取其余的数据,以便可以重用连接)?我的行是这样的:S3ObjectInputStream targetStream=confige.getObjectContent();XSSF工作簿excelf=新XSSF工作簿(targetStream);不确定如何抑制此警告。@ares SDK在后台维护一个连接池,可以为后续请求重新使用连接以获得更好的性能。如果在
//必要时从流中读取时引发异常,我认为这不起作用part@sworisbreathing我已经更新了这个例子,所以剩下的即使在//根据需要从流中读取部分期间出现异常,也会读取流的,它显示java.io.IOException:trusted read on closed stream
此try with resources代码样式将不起作用,因为资源将在执行catch
或finally
块之前关闭。因此,要使代码正常工作,您必须切换回旧式try
/catch
/finally
块,手动关闭finally
b