Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java AWS S3:上载大文件失败,重置异常:重置请求输入流失败_Java_Scala_Amazon Web Services_Amazon S3_Aws Sdk - Fatal编程技术网

Java AWS S3:上载大文件失败,重置异常:重置请求输入流失败

Java AWS S3:上载大文件失败,重置异常:重置请求输入流失败,java,scala,amazon-web-services,amazon-s3,aws-sdk,Java,Scala,Amazon Web Services,Amazon S3,Aws Sdk,有没有人能告诉我以下代码有什么问题,导致大型文件上载(>10GB)总是失败,并出现ResetException:Failed to reset request input stream 失败总是发生在一段时间之后(即在大约15分钟之后),这必然意味着上传过程只在中间某个地方执行失败。 以下是我试图调试该问题的内容: in.marksSupported()==false//检查我的FileInputStream是否支持标记 def upload(bucketName: String, keyNa

有没有人能告诉我以下代码有什么问题,导致大型文件上载(>10GB)总是失败,并出现
ResetException:Failed to reset request input stream

失败总是发生在一段时间之后(即在大约15分钟之后),这必然意味着上传过程只在中间某个地方执行失败。 以下是我试图调试该问题的内容:

  • in.marksSupported()==false//检查我的FileInputStream是否支持标记

    def upload(bucketName: String,  keyName: String,  file: File,  contentLength: Long,  contentType: String,  serverSideEncryption: Boolean = true,  storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = {
      val metaData = new ObjectMetadata
      metaData.setContentType(contentType)
      metaData.setContentLength(contentLength)
    
      if(serverSideEncryption) {
        metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)
      }
    
      val putRequest = new PutObjectRequest(bucketName, keyName, file)
      putRequest.setStorageClass(storageClass)
      putRequest.getRequestClientOptions.setReadLimit(100000)
      putRequest.setMetadata(metaData)
      tx.upload(putRequest)
    
    }
    }
    
    我高度怀疑这就是问题所在,因为S3SDK似乎希望在上传过程中的某个时刻执行重置操作,可能是在连接丢失或传输过程遇到错误的情况下

  • 将my
    FileInputStream
    包装在
    BufferedInputStream
    中以启用标记。现在调用.markssuported()中的
    返回
    true
    ,这意味着存在标记支持。奇怪的是,上传过程仍然失败,出现了同样的错误

  • 添加
    putRequest.getRequestClientOptions.setReadLimit(n)
    ,其中
    n=100000(100kb)和80000000(800mb)
    ,但仍会引发相同的错误。我怀疑是因为此参数用于重置流,如上所述,
    FileInputStream

    def upload(bucketName: String,  keyName: String,  file: File,  contentLength: Long,  contentType: String,  serverSideEncryption: Boolean = true,  storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = {
      val metaData = new ObjectMetadata
      metaData.setContentType(contentType)
      metaData.setContentLength(contentLength)
    
      if(serverSideEncryption) {
        metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)
      }
    
      val putRequest = new PutObjectRequest(bucketName, keyName, file)
      putRequest.setStorageClass(storageClass)
      putRequest.getRequestClientOptions.setReadLimit(100000)
      putRequest.setMetadata(metaData)
      tx.upload(putRequest)
    
    }
    }
    
  • 有趣的是,我的AWS开发帐户上没有出现同样的问题。我假设这只是因为dev帐户没有像我的生产帐户那样承受沉重的负载,这意味着上传过程可以尽可能顺利地执行,而不会出现任何故障

    请查看下面我的代码:

    object S3TransferExample {
    // in main class
    def main(args: Array[String]): Unit = {
        ...
        val file = new File("/mnt/10gbfile.zip")
        val in = new FileInputStream(file)
        // val in = new BufferedInputStream(new FileInputStream(file)) --> tried wrapping file inputstream in a buffered input stream, but it didn't help..
        upload("mybucket", "mykey", in, file.length, "application/zip").waitForUploadResult
        ...
    }
    
    val awsCred = new BasicAWSCredentials("access_key", "secret_key")
    val s3Client = new AmazonS3Client(awsCred)
    val tx = new TransferManager(s3Client)
    
    def upload(bucketName: String,  keyName: String,  inputStream: InputStream,  contentLength: Long,  contentType: String,  serverSideEncryption: Boolean = true,  storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = {
      val metaData = new ObjectMetadata
      metaData.setContentType(contentType)
      metaData.setContentLength(contentLength)
    
      if(serverSideEncryption) {
        metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)
      }
    
      val putRequest = new PutObjectRequest(bucketName, keyName, inputStream, metaData)
      putRequest.setStorageClass(storageClass)
      putRequest.getRequestClientOptions.setReadLimit(100000)
    
      tx.upload(putRequest)
     
    }
    }
    
    以下是完整的堆栈跟踪:

    Unable to execute HTTP request: mybucket.s3.amazonaws.com failed to respond
    org.apache.http.NoHttpResponseException: mybuckets3.amazonaws.com failed to respond
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260) ~[httpcore-4.3.2.jar:4.3.2]
        at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:283) ~[httpcore-4.3.2.jar:4.3.2]
        at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:251) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.conn.ManagedClientConnectionImpl.receiveResponseHeader(ManagedClientConnectionImpl.java:197) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271) ~[httpcore-4.3.2.jar:4.3.2]
        at com.amazonaws.http.protocol.SdkHttpRequestExecutor.doReceiveResponse(SdkHttpRequestExecutor.java:66) ~[aws-java-sdk-core-1.9.13.jar:na]
        at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123) ~[httpcore-4.3.2.jar:4.3.2]
        at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:685) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:487) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82) ~[httpclient-4.3.4.jar:4.3.4]
        at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57) ~[httpclient-4.3.4.jar:4.3.4]
        at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:685) [aws-java-sdk-core-1.9.13.jar:na]
        at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:460) [aws-java-sdk-core-1.9.13.jar:na]
        at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:295) [aws-java-sdk-core-1.9.13.jar:na]
        at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3710) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.AmazonS3Client.doUploadPart(AmazonS3Client.java:2799) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.AmazonS3Client.uploadPart(AmazonS3Client.java:2784) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadPartsInSeries(UploadCallable.java:259) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInParts(UploadCallable.java:193) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:125) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:129) [aws-java-sdk-s3-1.9.13.jar:na]
        at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:50) [aws-java-sdk-s3-1.9.13.jar:na]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_40]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_40]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_40]
        at java.lang.Thread.run(Thread.java:745) [na:1.8.0_40]
    com.amazonaws.ResetException: Failed to reset the request input stream;  If the request involves an input stream, the maximum stream buffer size can be configured via request.getRequestClientOptions().setReadLimit(int)
      at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:636)
      at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:460)
      at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:295)
      at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3710)
      at com.amazonaws.services.s3.AmazonS3Client.doUploadPart(AmazonS3Client.java:2799)
      at com.amazonaws.services.s3.AmazonS3Client.uploadPart(AmazonS3Client.java:2784)
      at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadPartsInSeries(UploadCallable.java:259)
      at com.amazonaws.services.s3.transfer.internal.UploadCallable.uploadInParts(UploadCallable.java:193)
      at com.amazonaws.services.s3.transfer.internal.UploadCallable.call(UploadCallable.java:125)
      at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:129)
      at com.amazonaws.services.s3.transfer.internal.UploadMonitor.call(UploadMonitor.java:50)
      at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
      at java.lang.Thread.run(Thread.java:745)
    Caused by: java.io.IOException: Resetting to invalid mark
      at java.io.BufferedInputStream.reset(BufferedInputStream.java:448)
      at com.amazonaws.internal.SdkBufferedInputStream.reset(SdkBufferedInputStream.java:106)
      at com.amazonaws.internal.SdkFilterInputStream.reset(SdkFilterInputStream.java:103)
      at com.amazonaws.event.ProgressInputStream.reset(ProgressInputStream.java:139)
      at com.amazonaws.internal.SdkFilterInputStream.reset(SdkFilterInputStream.java:103)
      at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:634) 
    

    S3不支持如此大的
    PUT
    请求

    在一次PUT中可以上载的最大对象是5 GB


    除此之外,您还必须使用多部分上传API,它允许每个部分为5GB,最大对象大小为5TB。对于小于5GB的文件,您也可以使用multipart,因为multipart支持并行上传部件。

    这看起来确实像一个bug。解决方案是使用另一个构造函数,它接受
    文件
    ,而不是
    输入流

    def upload(bucketName: String,  keyName: String,  file: File,  contentLength: Long,  contentType: String,  serverSideEncryption: Boolean = true,  storageClass: StorageClass = StorageClass.ReducedRedundancy ):Upload = {
      val metaData = new ObjectMetadata
      metaData.setContentType(contentType)
      metaData.setContentLength(contentLength)
    
      if(serverSideEncryption) {
        metaData.setSSEAlgorithm(ObjectMetadata.AES_256_SERVER_SIDE_ENCRYPTION)
      }
    
      val putRequest = new PutObjectRequest(bucketName, keyName, file)
      putRequest.setStorageClass(storageClass)
      putRequest.getRequestClientOptions.setReadLimit(100000)
      putRequest.setMetadata(metaData)
      tx.upload(putRequest)
    
    }
    }
    

    我调查过这个问题,说来话长

    结论是:通过向
    java
    命令行插入以下选项,将系统属性传递给java

    
    -Dcom.amazonaws.sdk.s3.defaultStreamBufferSize=您的最大输入大小
    


    这会告诉AmazonS3Client设置不可读取缓冲区的适当最大大小,该缓冲区将用于重新读取以供重试。

    也许您可以尝试使用as Amazon,将其用于大于100MB的对象。是的,我已经使用了TransferManager类(
    tx
    对象),这听起来像是java aws sdk中的一个bug,你试过报告吗?此外,您可能需要重新考虑是否需要上载10GB文件。。。你不能把它分开吗?@lolski你今天仍然有这个问题吗?不幸的是,我很久以前就停止开发这个产品了,所以我不知道S3@frunzaMy upload是否仍然存在这个问题,这意味着多部分上传已经由SDK API自动处理。我们可以参考多部分上传示例文档,它与我已有的文档类似:docs.aws.amazon.com/AmazonS3/latest/dev/HLuploadFileJava.htmlc您能发布一个指向该错误报告的链接吗?@bagi不,不幸的是,这并不能解决问题。您会将此选项放在
    Gradle.properties
    文件的Gradle设置中的什么位置?