每分钟运行一次的邮件程序的最佳 Rails 解决方案
我有一个应用程序,每分钟检查数据库中是否有当时应该发送的电子邮件。 我正在考虑将其作为一个 rake 任务,由 cron 作业每分钟运行一次。 对此是否有更好的解决方案?
据我所知,这并不理想,因为 rake 必须每分钟加载整个 Rails 环境,这会变得昂贵。
想法?
谢谢。
I have an application that checks a database every minute for any emails that are supposed to be sent out at that time. I was thinking about making this a rake task that would be run by a cron job every minute. Would there be a better solution to this?
From what I have read, this isn't ideal because rake has to load the entire rails environment every minute and this becomes expensive.
Thoughts?
Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
backgroundrb
。 然而,这会耗尽主 Rails 应用程序的内存,因为它将生成一个backgroundrb
独有的 Ruby 实例。wget
或curl
从crontab
中“生产”它,优点是它与您的主应用程序共享资源。 根据您的偏执程度,或者是否容易受到 DOS(或其他类型的攻击)的影响,将此类控制器暴露给外界(可能),您可以选择阻止从环回以外的地址访问此控制器的 URL(理想情况下在您的反向代理中,或者从控制器本身。)backgroundrb
. This, however, will eat up memory away from your main Rails app as it will spawn one Ruby instance exclusive tobackgroundrb
.SystemController
(or equivalent) in your main application, with various actions corresponding to the various household tasks your application should perform. You can "prod" it fromcrontab
usingwget
orcurl
, the advantage being that it shares resources with your main application. Depending on how paranoid or you are, or on how vulnerable to DOS (or other types of attacks) exposing such a controller to, possibly, the outside world, you may choose to block access to this controller's URL from addresses other than the loopback (ideally in your reverse proxy, alternatively from the controller itself.)一种非常简单的方法是使用一个脚本来......这
意味着您不会不断地重生 Rails 环境。
显然它有各种缺陷,但也有一些好处(例如,每分钟 1-Rake,如果 Rake 任务需要超过一分钟,Rake 将同时运行多次)
此外,Railscasts 剧集 < a href="http://railscasts.com/episodes/127-rake-in-background" rel="nofollow noreferrer">Rake 后台,Starling 和 Workling,以及 自定义守护进程可能会给你一些想法(他们正在准确地描述这个任务)
One really simple method would be to have a script that does..
..which means you are not constantly respawning the Rails environment.
Obviously it has various flaws, but also has some benefits (for example, with your 1-Rake-per-minute, it the Rake task takes more than one minute, Rake will be running multiple times at once)
Also, the Railscasts episodes Rake in Background, Starling and Workling, and Custom Daemon might give you some ideas (they are describing exactly this task)
事实证明,实际上有一个专门为此构建的东西:ar_mailer。 ar_mailer 将电子邮件排队到数据库中,然后使用 ar_mailer 命令定期将其发送出去。 您可以每分钟调用 ar_mailer。
ar_mailer 的好处在于,它基本上只需要对您已经发送电子邮件的方式进行很少的更改。 你只需要继承ar_mailer而不是ActiveMailer。 使用这种方法,您不必担心在后台运行 rake 任务、分叉进程或类似的事情 - 实际上您得到了一个真正的邮件服务器,其中的排队消息在实际发送邮件时被删除。 如果您的系统会大量发送电子邮件,则此功能非常重要。 我已经使用 ar_mailer 构建了一个社交网络 - 所以我可以证明它的稳健性。
这是一篇深入讨论 ar_mailer 的好文章 。 我强烈建议不要在这里推出自己的解决方案,因为 Eric 已经针对这个问题构建了一个经过时间考验的解决方案。
It turns out there's actually something built just for this: ar_mailer. ar_mailer queues up the e-mails into the DB and then sends them out periodically using the ar_mailer command. You can call ar_mailer every minute.
The nice thing about ar_mailer is that it basically requires very little change in terms of how you already send e-mails. You just need to inherit from ar_mailer instead of ActiveMailer. Using this method, you won't have to worry about running rake tasks in the background, forking processes, or anything like that - and in effect you get a real mail server with queued messages that are deleted when the mail is actually sent. This feature is important if you have a system that sends out large numbers of e-mail enmass. I've used ar_mailer to build a social network - so I can attest to its robustness.
Here's a good article that talks about ar_mailer in depth. I would strongly advise against rolling your own solution here as Eric has built a time-tested solution to this very problem.
我按照 Vlad 的建议(#2)进行操作,只接受本地请求,而且我非常偏执,还要求在 URL 上附加一个特定的查询字符串。
我有几个这样设置的定期操作。
I do what Vlad suggested (#2), with only local requests honored, and I'm paranoid enough to also require a specific query string tacked on to the url.
I have several periodic actions set up this way.