简体   繁体   English

如何处理 goroutine 中的错误

[英]How to handle errors in a goroutine

I have a service that use to upload file to AWS S3 .我有一项用于将文件上传到AWS S3的服务。 I was trying to use with goroutines and without to upload the file.我试图与 goroutines 一起使用而不上传文件。 If I upload the file without goroutines, it should wait till finish then give the response, and if I use goroutines it will run in the background and faster to response to the client-side.如果我在没有 goroutines 的情况下上传文件,它应该等到完成然后给出响应,如果我使用 goroutines,它将在后台运行并更快地响应客户端。

How about if that upload failed if I use goroutines?如果我使用 goroutines 上传失败怎么办? And then that file not uploaded to AWS S3 ?然后那个文件没有上传到AWS S3 Can you tell me to handle this how?你能告诉我如何处理这个吗?

here is my function to upload file这是我的 function 上传文件

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"))
    }
}

I was thinking as well how about if there many request to upload a file over 10000+ per 5-10mins?我也在想,如果有很多请求每 5-10 分钟上传超过 10000 个以上的文件怎么办? would some file can't be upload because too many request?是否会因为请求过多而无法上传某些文件?

This question is too broad for a single answer.这个问题太宽泛了,无法单独回答。 There are, broadly speaking, three possible approaches:从广义上讲,有三种可能的方法:

  1. Wait for your goroutines to complete to handle any errors.等待您的 goroutine 完成以处理任何错误。

  2. Ensure your goroutines can handle (or possibly ignore) any errors they encounter, such that returning an error never matters.确保您的 goroutine 可以处理(或可能忽略)它们遇到的任何错误,因此返回错误无关紧要。

  3. Have your goroutines log any errors, for handling later, possibly by a human, or possibly by some cleanup/retry function.让你的 goroutine 记录任何错误,以便以后处理,可能由人处理,或者可能由一些清理/重试 function。

Which approach is best depends on the situation.哪种方法最好取决于具体情况。

The problem is that when using a goroutine, you immediately return a success message to your client.问题是当使用 goroutine 时,您会立即向客户端返回一条成功消息。 If that's really the case, it means your goroutine needs to be able to recover in case of error when uploading to S3 (don't lose the image).如果确实如此,则意味着您的 goroutine 在上传到 S3 时需要能够在出错的情况下恢复(不要丢失图像)。 So either you take care of that, or you inform asynchronously your client that the upload failed, so the client can re-try.因此,要么您处理好,要么异步通知您的客户端上传失败,以便客户端可以重试。

For any asynchronous task - such as uploading a file in a background go-routine - one can write the uploading function in such a way to return a chan error to the caller.对于任何异步任务 - 例如在后台 go-routine 中上传文件 - 可以编写上传 function 以向调用者返回chan error The caller can then react to the file uploads eventual error (or nil for no error) at a later time by reading from the chan error .然后,调用者可以稍后通过读取chan error来对文件上传最终错误(或 nil 表示没有错误)做出反应。

However if you are accepting upload requests, I'd suggest instead to created a worker upload go-routine, that accepts file uploads via a channel.但是,如果您正在接受上传请求,我建议改为创建一个工作上传 go-routine,它通过通道接受文件上传。 An output "error" channel can track success/failure. output“错误”通道可以跟踪成功/失败。 And if need be, the error uploaded could be written back to the original upload channel queue (including a retry tally & retry max - so a problematic payload does not loop forever).如果需要,可以将上传的错误写回原始上传通道队列(包括重试计数和重试最大值 - 因此有问题的有效负载不会永远循环)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM