如何处理 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。如果需要,上传的错误可以写回原始上传通道队列(包括重试计数和重试最大值 - 所以有问题的有效负载不会永远循环)。

这个问题太宽泛,无法单独回答。从广义上讲,有三种可能的方法:

  1. 等待您的 goroutines 完成以处理任何错误。

  2. 确保您的 goroutines 可以处理(或可能忽略)它们遇到的任何错误,这样返回错误就无关紧要了。

  3. 让你的 goroutines 记录任何错误,以便稍后处理,可能由人类处理,也可能由某些 cleanup/retry 函数处理。

哪种方法最好取决于具体情况。