在不加载多个环境的情况下为多个 Rails 应用程序安排任务

发布于 2024-09-25 03:39:22 字数 309 浏览 5 评论 0原文

在我们的服务器上,我们使用 Phusion Passenger 部署了多个 Rails 应用程序。每个应用程序都有一组必须定期计划和运行的任务(通常是清除缓存、发送邮件等)。

我在野外看到的所有示例通常都显示一个单独的守护进程,用于处理应用程序的计划任务。但是,这需要守护程序加载应用程序的环境。虽然这在您部署一两个应用程序时有效,但当服务器上可能部署 100 个应用程序时,它就无法扩展。 (例如,每个“守护进程”加载整个 Rails 环境加上应用程序代码,可能超过 50MB。部署 100 个应用程序,仅在调度程序守护进程中就消耗了 5GB。)

有人解决了这个问题吗?

On our servers we have deployed multiple Rails applications using Phusion Passenger. Each application has a set of tasks that must be scheduled and run periodically (the usual clear caches, send mail, etc.)

All the examples I've seen in the wild usually show a separate daemon that handles the scheduled tasks for an application. However, this requires that the daemon load the app's environment. While this works when you have one or two apps deployed, it does not scale when there might be 100 apps deployed on a server. (For example, each "daemon" loads up an entire Rails environment plus the app code, which could be well over 50MB. Deploy 100 apps, and you're chewing up 5GB just in scheduler daemons.)

Has anyone solved this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

用心笑 2024-10-02 03:39:23

我有类似的问题需要解决。我发现这些解决方案可用:

  1. 在新进程中运行由 Cron 初始化的任务
    • 缺点:新实例的启动时间
  2. 运行任务 的启动时间
    • 缺点:守护进程占用内存
  3. ,在现有实例内的线程中运行任务
    • 缺点:乘客会生成 X 个实例,并且很难确保 1 个实例中仅运行 1 个线程。
    • 缺点:调用请求-响应周期之外的任何内容可能会导致乘客泄漏或不稳定。
  4. 运行由现有实例的 HTTP 请求初始化的任务
    • 优点:无启动时间,使用现有实例,确保单次执行,对乘客生命周期安全
    • 缺点:在任务执行时锁定一个应用实例 - 如果应用是线程安全的,但需要调查,这可能不是问题,因为线程安全在 Rails 中是相当新的事物。
    • 优点

最后我决定采用选项 4。使用 cron 和curl(或 wget),并拥有只能由本地主机访问的 CronController

I had similar issue to solve. I found these solutions available:

  1. run tasks initialized by Cron in new process
    • cons: startup time for new instance
  2. run tasks in long living daemon
    • cons: daemon occupying memory
  3. run tasks in thread inside existing instance
    • cons: passenger spawns X instances and it is hard to ensure that only 1 thread in 1 instance will be run.
    • cons: invoking anything outside request-response cycle may create leaks or instability in passenger.
  4. run tasks initialized by HTTP request to existing instance
    • pro: no startup time, uses existing instance, ensures single execution, safe for passanger lifecycle
    • cons: locks one app instance for time of task execution - this may be not an issue if app is thread-safe but needs investigation, as thread-safety is quite new thing in Rails.

Finally I decided to go with option 4. Using cron and curl (or wget), and own CronController accessible only to localhost.

旧梦荧光笔 2024-10-02 03:39:22

我认为答案取决于您的需求。如果这些任务需要相当多的时间,那么最简单的解决方案就是使用守护程序以传统方式完成。如果您想依赖 Rails 堆栈,那么您必须将其加载到内存中才能使用它 - 您将无法转义它。

如果您的任务不需要太多时间,那么您可以执行以下操作:使用可用的方法(例如 delayed_job< /a>),但定期启动和停止守护进程(请参阅 此处获取一些提示)。因此,您可以在上午 9 点启动 10 个守护进程,并在上午 10 点停止它们,然后您可以启动另外 10 个守护进程,依此类推。启动和停止可以使用 cron 或任何类似的工具来完成。

但是,如果您的任务非常简单并且在每个应用程序中都非常相似,那么您只需编写脚本来完成这项工作即可。例如,如果“通常清除缓存”意味着您从某些目录中删除一些文件,那么只需将其放入脚本并定期运行即可。发送电子邮件也可以通过脚本(ruby 程序)来完成。在 ruby​​ 中从数据库中获取任何数据真的很容易。所以这个程序可以定期检查数据库中的mails_queue表并发送电子邮件。如果您的应用程序类似,那么实现起来将非常简单。

也许有一些现成的解决方案,但我还没有听说过。

I think that the answer depends on your needs. If those tasks take quite a lot of time, then the simplest solution is to do it in traditional way with daemon. If you want to rely on Rails stack then you must load it to memory in order to use it - you won't escape it.

If your tasks don't need much time, then you can do something like this: use methods that are availble (like delayed_job) but start and stop daemon periodicaly (see here for some tips). So you can start 10 daemons at 9 a.m. and stop them at 10 a.m. Then you can start another 10 and so on. Starting and stopping can be done with cron or any similar tool.

However if your tasks are really simple and very similar in each application, then you can just write your scripts to do the job. On example if "usual clear cache" means that you delete some files from some directories, then just put it to script and run in periodicaly. Sending email can also be done through a script (ruby program). It is really easy to fetch any data from db in ruby. So this program can periodicaly check something like mails_queue table in databases and send emails. If your applications are similar then it will be quite simple to achieve.

Maybe there are some ready solutions to this, but I haven't heard about them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文