猿问

golang中的生产者消费者-并发与并行?

我正在研究纯粹使用 Golang 的后端架构。我有一个 API,用于将文件上传到 golang 服务器,然后我将文件传输到云存储(从 golang 服务器本身)。现在,我希望两个传输都是独立的,这样最终用户就不必在上传文件后等待响应。

End User -> Golang Server ->[Concurrency/Parallelism] -> Cloud Storage

现在,我想到了两种方法:

  1. 用户完成上传并将文件传输到云后,立即创建一个 goroutine。

  2. 将文件处理程序插入队列,不同的进程将读取此队列并将文件传输到云存储(多生产者 - 单消费者模型)。

我找到了使用 goroutine 和 channels 执行此操作的示例,但我认为这将创建与上传一样多的 goroutine。我想使用第二个选项,但无法理解如何在 golang 中进行操作?

另外,请建议我是否使用了错误的方法,并且还有其他一些有效的方法可以做到这一点。

更新

有关要求和约束的详细信息:
1. 我使用 AWS S3 作为云存储。如果在某个时候,从 Go 服务器到 Amazon S3 的上传失败,文件处理程序应该保持原样以记录失败的上传。(我没有优先考虑这一点,我可能会根据客户的反馈进行更改)
2.上传到 Amazon S3 成功完成后,文件将立即从 Go 服务器中删除,以避免重复上传。此外,如果文件以相同的名称上传,它将在 Amazon S3 中被替换。
3.正如评论中所指出的,我可以使用频道作为队列。是否可以使用 Go 的 Channels 和 goroutines 来设计上述架构?


梦里花落0921
浏览 128回答 2
2回答

侃侃尔雅

上传文件的用户可以容忍错误,然后重试。但是当上传的文件只存在于它上传到的机器上时存在危险,并且在上传到云存储之前出现问题。在这种情况下,文件将丢失,这对用户来说将是一个无赖。这是通过良好的架构解决的。这是一个先进先出的队列模式。这种模式的一个最受欢迎的 Go 实现是go-workers,它可能由Redis数据库支持。假设在任何给定时间有n个服务器运行您的服务。假设您的后端代码编译了两个单独的二进制文件,一个服务器二进制文件和一个工作二进制文件。理想情况下,接受文件上传的机器都会挂载一个共享的网络文件系统,这样:用户上传文件到服务器一种。服务器将一条记录添加到工作队列中,该记录包含来自 Redis 存储的唯一 ID。湾 这个唯一的 ID 用于创建文件名,文件直接从用户上传到 NFS 服务器上的临时存储。请注意,该文件永远不会驻留在运行服务器的机器的存储中。文件由工人上传到云存储一种。worker从具有唯一 ID 的工作队列中取出下一个待办事项记录湾 使用唯一 ID 在 NFS 服务器上查找文件,工作人员将文件上传到云存储C。成功后,worker更新工作队列中的记录以反映成功d. worker删除 NFS 服务器上的文件通过将服务器流量和工作队列大小作为两个独立的指标进行监控,可以确定应该分别运行服务器/工作器服务的服务器数量。

米脂

Marcio Castilho 写了一篇关于类似问题的好文章。它可以在使用 golang 处理每分钟一百万个请求中找到。他展示了他所犯的错误以及他为纠正这些错误所采取的步骤。一般学习通道、goroutines 和并发的使用的好资源。charneykaye提到的go-workers也是很好的来源。
随时随地看视频慕课网APP

相关分类

Go
我要回答