运行 Rails 中的大量长 运行 后台作业
Running large amount of long running background jobs in Rails
我们正在构建一个网络应用程序,用户将在其中上传可能需要在后台处理的大文件。该任务涉及调用第 3 方 API,因此每项工作可能需要几个小时才能完成。我们正在使用 DelayedJob 来 运行 后台作业。每个用户启动一个后台作业,每个后台作业都需要几个小时才能完成,这将很快增加很多后台作业。我想知道为此设置部署的最佳方法是什么?我们目前托管在 DigitalOcean 上。我已经启动了 10 个 DelayedJob worker。每个(理想情况下)占用 157MB。当主动 运行ning 时,它使用大约 900 MB。我们现在的用户群很小,所以这不是问题,但很快就会成为问题。所以在一个 4GB 的 droplet 上,我可能 运行 一次有 2 或 3 个工人。我们应该如何处理这个问题?我们是否应该考虑使用 DigitalOcean 的 API 按需自动旋转廉价的液滴?我们应该改为按月订阅高内存水滴吗?如果我们使用自动旋转的水滴,我们应该坚持使用 DigitalOcean 还是 Heroku 更有意义?或者整个方法是错误的,我们应该从一个完全不同的方向来处理它吗?任何 help/advice 将不胜感激。
谢谢!
听起来您在 DigitalOcean 主机上可以 运行 的工作人员数量似乎受到内存限制。
如果您担心扩展问题,我会专注于让工作人员尽可能高效。您是否做过任何基准测试以了解 900MB 内存的分配位置?我不确定这些工作的性质是什么,但你提到了大文件。您是将这些文件的内容读入内存,还是流式传输它们?您使用的是 SQL 可以调整的数据库吗?当您可以使用批处理端点时,您是否进行了许多小的 API 调用?您是否正在分配必须随后被垃圾收集的中间变量?发送前可以压缩文件吗?
查看工作结构本身。我发现后台工作最适合许多较小的工作而不是一个较大的工作。这允许并行执行,并且在所有 worker 之间实现更多的负载平衡。你甚至可以拥有一份可以产生其他工作的工作。如果您需要一个作业来在一组作业完成时编排回调,可以使用 https://github.com/salsify/delayed_job_groups_plugin 处的 DelayedJobGroup 插件,它允许您仅在同级作业完成后调用最终作业。我的目标是将单个作业的执行时间控制在 30 秒以下。这是任意的,但它说明了我所说的较小工作的意思。
亚马逊等一些托管服务提供商提供现货实例,您可以在没有保证可用性的服务器上支付较低的价格。这些与我之前提到的更少的工作方法相得益彰。
最后,Ruby 可能不是完成这项工作的正确工具。有更快的语言,如果你受限于内存或 CPU,你可能会考虑用另一种语言编写这些工作和他们的工作人员,如 Javascript、Go 或 Rust。这些可以与 Ruby 堆栈很好地配对,但将计算量大的子例程卸载到更快的语言。
最后,就像许多扩展问题一样,如果您的钱多于时间,您总是可以投入更多的硬件。至少有一段时间。
我认为内存和时间对你来说是个更大的问题。你必须在这个过程中使用 sidekiq gem 因为它会消耗更少的时间和内存消耗来完成同样的工作,因为它使用 redis 作为数据库,它是键值对 db.if 问题继续与 java 脚本。
我们正在构建一个网络应用程序,用户将在其中上传可能需要在后台处理的大文件。该任务涉及调用第 3 方 API,因此每项工作可能需要几个小时才能完成。我们正在使用 DelayedJob 来 运行 后台作业。每个用户启动一个后台作业,每个后台作业都需要几个小时才能完成,这将很快增加很多后台作业。我想知道为此设置部署的最佳方法是什么?我们目前托管在 DigitalOcean 上。我已经启动了 10 个 DelayedJob worker。每个(理想情况下)占用 157MB。当主动 运行ning 时,它使用大约 900 MB。我们现在的用户群很小,所以这不是问题,但很快就会成为问题。所以在一个 4GB 的 droplet 上,我可能 运行 一次有 2 或 3 个工人。我们应该如何处理这个问题?我们是否应该考虑使用 DigitalOcean 的 API 按需自动旋转廉价的液滴?我们应该改为按月订阅高内存水滴吗?如果我们使用自动旋转的水滴,我们应该坚持使用 DigitalOcean 还是 Heroku 更有意义?或者整个方法是错误的,我们应该从一个完全不同的方向来处理它吗?任何 help/advice 将不胜感激。
谢谢!
听起来您在 DigitalOcean 主机上可以 运行 的工作人员数量似乎受到内存限制。
如果您担心扩展问题,我会专注于让工作人员尽可能高效。您是否做过任何基准测试以了解 900MB 内存的分配位置?我不确定这些工作的性质是什么,但你提到了大文件。您是将这些文件的内容读入内存,还是流式传输它们?您使用的是 SQL 可以调整的数据库吗?当您可以使用批处理端点时,您是否进行了许多小的 API 调用?您是否正在分配必须随后被垃圾收集的中间变量?发送前可以压缩文件吗?
查看工作结构本身。我发现后台工作最适合许多较小的工作而不是一个较大的工作。这允许并行执行,并且在所有 worker 之间实现更多的负载平衡。你甚至可以拥有一份可以产生其他工作的工作。如果您需要一个作业来在一组作业完成时编排回调,可以使用 https://github.com/salsify/delayed_job_groups_plugin 处的 DelayedJobGroup 插件,它允许您仅在同级作业完成后调用最终作业。我的目标是将单个作业的执行时间控制在 30 秒以下。这是任意的,但它说明了我所说的较小工作的意思。
亚马逊等一些托管服务提供商提供现货实例,您可以在没有保证可用性的服务器上支付较低的价格。这些与我之前提到的更少的工作方法相得益彰。
最后,Ruby 可能不是完成这项工作的正确工具。有更快的语言,如果你受限于内存或 CPU,你可能会考虑用另一种语言编写这些工作和他们的工作人员,如 Javascript、Go 或 Rust。这些可以与 Ruby 堆栈很好地配对,但将计算量大的子例程卸载到更快的语言。
最后,就像许多扩展问题一样,如果您的钱多于时间,您总是可以投入更多的硬件。至少有一段时间。
我认为内存和时间对你来说是个更大的问题。你必须在这个过程中使用 sidekiq gem 因为它会消耗更少的时间和内存消耗来完成同样的工作,因为它使用 redis 作为数据库,它是键值对 db.if 问题继续与 java 脚本。