如何处理 goroutine 中的错误
How to handle errors in a goroutine
我有一项服务用于将文件上传到 AWS S3。我试图与 goroutines 一起使用而不上传文件。如果我在没有 goroutines 的情况下上传文件,它应该等到完成然后给出响应,如果我使用 goroutines 它将 运行 在后台并且更快地响应客户端。
如果我使用 goroutines 上传失败怎么办?然后那个文件没有上传到 AWS S3?你能告诉我如何处理吗?
这是我上传文件的函数
func uploadToS3(s *session.Session, size int64, name string , buffer []byte)( string , error) {
tempFileName := "pictures/" + bson.NewObjectId().Hex() + "-" + filepath.Base(name)
_, err := s3.New(s).PutObject(&s3.PutObjectInput{
Bucket: aws.String("myBucketNameHere"),
Key: aws.String(tempFileName),
ACL: aws.String("public-read"),
Body: bytes.NewReader(buffer),
ContentLength: aws.Int64(int64(size)),
ContentType: aws.String(http.DetectContentType(buffer)),
ContentDisposition: aws.String("attachment"),
ServerSideEncryption: aws.String("AES256"),
StorageClass: aws.String("INTELLIGENT_TIERING"),
})
if err != nil {
return "", err
}
return tempFileName, err
}
func UploadFile(db *gorm.DB) func(c *gin.Context) {
return func(c *gin.Context) {
file, err := c.FormFile("file")
f, err := file.Open()
if err != nil {
fmt.Println(err)
}
defer f.Close()
buffer := make([]byte, file.Size)
_, _ = f.Read(buffer)
s, err := session.NewSession(&aws.Config{
Region: aws.String("location here"),
Credentials: credentials.NewStaticCredentials(
"id",
"key",
"",
),
})
if err != nil {
fmt.Println(err)
}
go uploadToS3(s, file.Size, file.Filename, buffer)
c.JSON(200, fmt.Sprintf("Image uploaded successfully"))
}
}
我也在想,如果有很多请求每 5-10 分钟上传超过 10000 个文件怎么办?会不会因为请求太多而无法上传某些文件?
问题在于,当使用 goroutine 时,您会立即 return 向您的客户端发送一条成功消息。如果确实如此,则意味着您的 goroutine 需要能够在上传到 S3 时出错时恢复(不要丢失图像)。所以要么你处理好,要么异步通知你的客户端上传失败,这样客户端可以重试。
对于任何异步任务 - 例如在后台 go-routine 中上传文件 - 可以将上传函数写成 return 一个 chan error
给调用者。然后,调用者可以在稍后通过读取 chan error
.
对文件上传最终错误(或 nil 表示没有错误)做出反应
但是,如果您接受上传请求,我建议改为创建一个工作上传 go-routine,它通过通道接受文件上传。一个输出 "error" 通道可以跟踪 success/failure。如果需要,上传的错误可以写回原始上传通道队列(包括重试计数和重试最大值 - 所以有问题的有效负载不会永远循环)。
这个问题太宽泛,无法单独回答。从广义上讲,有三种可能的方法:
等待您的 goroutines 完成以处理任何错误。
确保您的 goroutines 可以处理(或可能忽略)它们遇到的任何错误,这样返回错误就无关紧要了。
让你的 goroutines 记录任何错误,以便稍后处理,可能由人类处理,也可能由某些 cleanup/retry 函数处理。
哪种方法最好取决于具体情况。
我有一项服务用于将文件上传到 AWS S3。我试图与 goroutines 一起使用而不上传文件。如果我在没有 goroutines 的情况下上传文件,它应该等到完成然后给出响应,如果我使用 goroutines 它将 运行 在后台并且更快地响应客户端。
如果我使用 goroutines 上传失败怎么办?然后那个文件没有上传到 AWS S3?你能告诉我如何处理吗?
这是我上传文件的函数
func uploadToS3(s *session.Session, size int64, name string , buffer []byte)( string , error) {
tempFileName := "pictures/" + bson.NewObjectId().Hex() + "-" + filepath.Base(name)
_, err := s3.New(s).PutObject(&s3.PutObjectInput{
Bucket: aws.String("myBucketNameHere"),
Key: aws.String(tempFileName),
ACL: aws.String("public-read"),
Body: bytes.NewReader(buffer),
ContentLength: aws.Int64(int64(size)),
ContentType: aws.String(http.DetectContentType(buffer)),
ContentDisposition: aws.String("attachment"),
ServerSideEncryption: aws.String("AES256"),
StorageClass: aws.String("INTELLIGENT_TIERING"),
})
if err != nil {
return "", err
}
return tempFileName, err
}
func UploadFile(db *gorm.DB) func(c *gin.Context) {
return func(c *gin.Context) {
file, err := c.FormFile("file")
f, err := file.Open()
if err != nil {
fmt.Println(err)
}
defer f.Close()
buffer := make([]byte, file.Size)
_, _ = f.Read(buffer)
s, err := session.NewSession(&aws.Config{
Region: aws.String("location here"),
Credentials: credentials.NewStaticCredentials(
"id",
"key",
"",
),
})
if err != nil {
fmt.Println(err)
}
go uploadToS3(s, file.Size, file.Filename, buffer)
c.JSON(200, fmt.Sprintf("Image uploaded successfully"))
}
}
我也在想,如果有很多请求每 5-10 分钟上传超过 10000 个文件怎么办?会不会因为请求太多而无法上传某些文件?
问题在于,当使用 goroutine 时,您会立即 return 向您的客户端发送一条成功消息。如果确实如此,则意味着您的 goroutine 需要能够在上传到 S3 时出错时恢复(不要丢失图像)。所以要么你处理好,要么异步通知你的客户端上传失败,这样客户端可以重试。
对于任何异步任务 - 例如在后台 go-routine 中上传文件 - 可以将上传函数写成 return 一个 chan error
给调用者。然后,调用者可以在稍后通过读取 chan error
.
但是,如果您接受上传请求,我建议改为创建一个工作上传 go-routine,它通过通道接受文件上传。一个输出 "error" 通道可以跟踪 success/failure。如果需要,上传的错误可以写回原始上传通道队列(包括重试计数和重试最大值 - 所以有问题的有效负载不会永远循环)。
这个问题太宽泛,无法单独回答。从广义上讲,有三种可能的方法:
等待您的 goroutines 完成以处理任何错误。
确保您的 goroutines 可以处理(或可能忽略)它们遇到的任何错误,这样返回错误就无关紧要了。
让你的 goroutines 记录任何错误,以便稍后处理,可能由人类处理,也可能由某些 cleanup/retry 函数处理。
哪种方法最好取决于具体情况。