Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.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
Go AWS S3下载程序内存不足_Go_Amazon S3 - Fatal编程技术网

Go AWS S3下载程序内存不足

Go AWS S3下载程序内存不足,go,amazon-s3,Go,Amazon S3,我在使用golang客户端从AWS S3 bucket下载大文件时遇到问题,我不是golang的专家,因此我非常感谢您的帮助 我正在创建一个简单的API,它使用gin-gonic框架公开一个端点,当有人向该端点发送请求时,应用程序将从AWS S3 bucket下载一个巨大的CSV文件,并将该文件的内容保存在本地数据库中 当文件大小为200 mb时,它可以正常工作,但对于更大的文件,例如500 mb,我开始出现内存不足错误 我正在使用这部分代码创建会话并加载文件: sess, _ := sessi

我在使用golang客户端从AWS S3 bucket下载大文件时遇到问题,我不是golang的专家,因此我非常感谢您的帮助

我正在创建一个简单的API,它使用gin-gonic框架公开一个端点,当有人向该端点发送请求时,应用程序将从AWS S3 bucket下载一个巨大的CSV文件,并将该文件的内容保存在本地数据库中

当文件大小为200 mb时,它可以正常工作,但对于更大的文件,例如500 mb,我开始出现内存不足错误

我正在使用这部分代码创建会话并加载文件:

sess, _ := session.NewSession(&aws.Config{
    Region: aws.String("us-west-2")},
)

downloader := s3manager.NewDownloader(sess)

getInput := &s3.GetObjectInput{
    Bucket: aws.String("the bucket name"),
    Key:    aws.String("the file path"),
}

buff := new(aws.WriteAtBuffer)

_, err := downloader.Download(buff, getInput)

if err != nil {    
        return nil, errors.New(err, "error downloading file")
}

return buff.Bytes(), nil
在本部分之后,我有一个服务,它接收字节并使用golang CSV阅读器迭代文件内容:

csv.NewReader(bytes.NewReader(theBytes))
在读取器接收字节之前下载文件内容时,会出现此问题

这是我得到的堆栈跟踪:

09:28:04.390    github.com/gin-gonic/gin.(*Engine).Run(0xc000318f00, 0xc00060ff68, 0x1, 0x1, 0x0, 0x0)
/go/pkg/mod/github.com/gin-gonic/gin@v1.6.3/gin.go:301 +0x14a
09:28:04.389    net/http.(*Server).ListenAndServe(0xc00017c000, 0xc00017c000, 0xc00060ff08)
/usr/local/go/src/net/http/server.go:2866 +0xb7
09:28:04.388    net/http.(*Server).Serve(0xc00017c000, 0x13512c0, 0xc000122780, 0x0, 0x0)
/usr/local/go/src/net/http/server.go:2937 +0x266
09:28:04.387    net.(*netFD).accept(0xc0001a9000, 0x173d6ba672b673f9, 0x0, 0x0)
/usr/local/go/src/net/fd_unix.go:172 +0x45
09:28:04.387    net.(*TCPListener).accept(0xc000122780, 0x6061c7c9, 0xc00046dd28, 0x4d5286)
/usr/local/go/src/net/tcpsock_posix.go:139 +0x32
09:28:04.387    net.(*TCPListener).Accept(0xc000122780, 0xc00046dd78, 0x18, 0xc000000180, 0x70beec)
/usr/local/go/src/net/tcpsock.go:261 +0x65
09:28:04.385    internal/poll.(*pollDesc).wait(0xc0001a9018, 0x72, 0x0, 0x0, 0x1170293)
/usr/local/go/src/internal/poll/fd_poll_runtime.go:87 +0x45
09:28:04.385    internal/poll.(*pollDesc).waitRead(...)
/usr/local/go/src/internal/poll/fd_poll_runtime.go:92
09:28:04.385    internal/poll.(*FD).Accept(0xc0001a9000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/internal/poll/fd_unix.go:394 +0x1fc
09:28:04.384    github.com/aws/aws-sdk-go/service/s3/s3manager.(*downloader).tryDownloadChunk(0xc000399b00, 0xc0008be280, 0x133c320, 0xc000174300, 0x0, 0x0, 0x0)
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/service/s3/s3manager/download.go:463 +0x189 fp=0xc0008bbe28 sp=0xc0008bbd80 pc=0xe48409
09:28:04.384    github.com/aws/aws-sdk-go/service/s3/s3manager.(*downloader).downloadChunk(0xc000399b00, 0x133c160, 0xc000dd0a50, 0x1c700000, 0x500000, 0x0, 0x0, 0x0, 0x0, 0x0)
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/service/s3/s3manager/download.go:424 +0x236 fp=0xc0008bbee8 sp=0xc0008bbe28 pc=0xe480d6
09:28:04.384    runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc0008bbfd8 sp=0xc0008bbfd0 pc=0x471461
09:28:04.384    internal/poll.runtime_pollWait(0x7f5414dee788, 0x72, 0x0)
/usr/local/go/src/runtime/netpoll.go:222 +0x55
09:28:04.384    io.copyBuffer(0x133c320, 0xc000174300, 0x133d9c0, 0xc000088080, 0xc00088e000, 0x8000, 0x8000, 0xc000b52d80, 0x0, 0x0)
/usr/local/go/src/io/io.go:411 +0x206 fp=0xc0008bbd80 sp=0xc0008bbd08 pc=0x47ea66
09:28:04.384    io.Copy(...)
/usr/local/go/src/io/io.go:368
09:28:04.384    github.com/aws/aws-sdk-go/service/s3/s3manager.(*downloader).downloadPart(0xc000399b00, 0xc000d98000)
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/service/s3/s3manager/download.go:373 +0x14d fp=0xc0008bbfd0 sp=0xc0008bbee8 pc=0xe47b6d
09:28:04.384    github.com/aws/aws-sdk-go/service/s3/s3manager.(*dlchunk).Write(0xc000174300, 0xc00088e000, 0x400, 0x8000, 0x400, 0x0, 0x0)
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/service/s3/s3manager/download.go:583 +0x72 fp=0xc0008bbd08 sp=0xc0008bbcb8 pc=0xe48d72
09:28:04.384    created by github.com/aws/aws-sdk-go/service/s3/s3manager.(*downloader).download
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/service/s3/s3manager/download.go:317 +0x1f4
09:28:04.384    goroutine 1 [IO wait]:
09:28:04.383    runtime.sysMap(0xc0e0000000, 0x20000000, 0x19edcb8)
/usr/local/go/src/runtime/mem_linux.go:169 +0xc6
09:28:04.383    runtime.(*mheap).allocSpan(0x19d23a0, 0xe385, 0x400100, 0x19edcc8, 0xffffffff00000001)
/usr/local/go/src/runtime/mheap.go:1160 +0x6b6
09:28:04.383    runtime.systemstack(0x46f554)
/usr/local/go/src/runtime/asm_amd64.s:370 +0x66
09:28:04.383    runtime.mallocgc(0x1c7095fb, 0xfa59e0, 0x1, 0x0)
/usr/local/go/src/runtime/malloc.go:1070 +0x938 fp=0xc0008bbc20 sp=0xc0008bbb80 pc=0x40fab8
09:28:04.383    runtime.makeslice(0xfa59e0, 0x1c7095fb, 0x1c7095fb, 0xc0aa006000)
/usr/local/go/src/runtime/slice.go:98 +0x6c fp=0xc0008bbc50 sp=0xc0008bbc20 pc=0x45056c
09:28:04.383    runtime.throw(0x1180cb4, 0x16)
/usr/local/go/src/runtime/panic.go:1116 +0x72
09:28:04.383    runtime.(*mheap).alloc.func1()
/usr/local/go/src/runtime/mheap.go:907 +0x65
09:28:04.383    runtime.(*mheap).alloc(0x19d23a0, 0xe385, 0xc0008b0101, 0x19b9ca0)
/usr/local/go/src/runtime/mheap.go:901 +0x85
09:28:04.383    runtime.mstart()
/usr/local/go/src/runtime/proc.go:1116
09:28:04.383    runtime.systemstack_switch()
/usr/local/go/src/runtime/asm_amd64.s:330 fp=0xc0008bbb80 sp=0xc0008bbb78 pc=0x46f680
09:28:04.383    runtime.(*mheap).sysAlloc(0x19d23a0, 0x1c800000, 0x42da97, 0x19d23a8)
/usr/local/go/src/runtime/malloc.go:727 +0x1e5
09:28:04.383    runtime.(*mheap).grow(0x19d23a0, 0xe385, 0x0)
/usr/local/go/src/runtime/mheap.go:1344 +0x85
09:28:04.383    runtime.largeAlloc(0x1c7095fb, 0xc0008b0101, 0x6)
/usr/local/go/src/runtime/malloc.go:1177 +0x92
09:28:04.383    runtime.mallocgc.func1()
/usr/local/go/src/runtime/malloc.go:1071 +0x46
09:28:04.383    goroutine 225306 [running]:
09:28:04.383    github.com/aws/aws-sdk-go/aws.(*WriteAtBuffer).WriteAt(0xc000dd0a50, 0xc00088e000, 0x400, 0x8000, 0x1c7091fb, 0x0, 0x0, 0x0)
/go/pkg/mod/github.com/aws/aws-sdk-go@v1.37.7/aws/types.go:193 +0x105 fp=0xc0008bbcb8 sp=0xc0008bbc50 pc=0xd18445
09:28:04.382    runtime stack:
09:28:04.379    fatal error: runtime: out of memory
我的问题是,是否有任何方法可以解决这个问题,使用不同的方法下载代码中的文件(下载程序上可能有不同的设置)或。。。相反,如果我需要分割bucket中的文件内容,以减小大小并按部分下载文件

另一个选择是增加golang在应用程序运行时使用的内存

我不知道在我的情况下,哪种可能是最好的解决方案,你有什么建议


我感谢您的任何建议或推荐,非常感谢

通过使用
下载程序
您无法在文件下载时处理该文件:它同时下载不同的块,因此您不会按顺序接收字节

如果您想在下载时处理字节,可以尝试使用
s3.s3
。这会按顺序下载对象,但只使用一个goroutine,因此速度会较慢

比如:

sess,\:=session.NewSession(&aws.Config){
地区:aws.String(“us-west-2”)},
)
s3Client:=s3.New(sess)
getInput:=&s3.GetObjectInput{
Bucket:aws.String(“Bucket名称”),
Key:aws.String(“文件路径”),
}
resp,err:=s3Client.GetObjectWithContext(context.TODO(),getInput)
如果出错!=零{
返回nil,fmt.Errorf(“下载文件时出错:%v”,err)
}
延迟响应主体关闭()
rd:=csv.NewReader(分别为正文)

不要将整个文件读入内存,然后进行处理,处理过程是在读取时,一行一行地进行。我该怎么做,你能给我一些提示吗?因为下载程序返回文件的整个字节,然后我读取字节,我不明白在字节仍在下载的情况下如何处理填充内容。不如直接将其下载到临时文件而不是内存中?@AndrewSullivan:我怀疑当第一个参数特别是
io.WriterAt
时,
downloader.Download
是否会缓冲整个有效负载。函数采用writer参数的意义在于它不需要缓冲所有数据。我不知道“golang中IO api的错误”是什么,但是如果你不将整个内容加载到内存中,那么你就不应该有同样的问题,导致你没有足够的内存来获得答案,我将测试这种方法,看看它是否有效。我有一个问题:我不明白如果还没有文件的完整字节,读者会如何阅读正文(resp.body),如果我没有遗漏一些东西,这就是这种方法的想法,对吗?嗨,是的,你的想法是正确的。如果查看
io.Reader
io.Writer
接口,您将看到使用字节片调用Read。字节片的大小可能比您试图下载的文件小得多,这意味着您需要多次读取调用才能获得整个文件。这使得文件可以分块处理,而不必将整个文件存储在内存中。您可以将GetObjectWithContext调用看作是启动一个新的goroutine,它填充传递给Read调用的字节片。