我来自PHP环境(至少在web开发方面)和Ruby的美丽世界,所以我可能会有一些愚蠢的问题。我想在不使用PHP时有一些根本不同的选项。
在PHP中,我们使用memcache来存储我们想要在页面顶部的栏中显示的警报。当发生某些事件产生警报(例如正在制作新的博客文章)时,每5分钟左右运行一次的cron脚本会将该信息放入内存缓存中。
现在,当用户访问该网站时,我们会查看内存缓存,以查找他们尚未解散的任何警报,并显示它们。
我猜测我在Rails中可以采取不同的做法,就是绕过对cron脚本的需求,并且还需要在每个请求中查看内存缓存,方法是使用在单个运行中运行的单例和轮询进程单独的线程从memcache复制到这个单例。从理论上讲,这将比每次请求检查memcache更优化,并且还将轮询逻辑封装到一个位置,而不是在cron任务和查找逻辑之间进行拆分。
我的问题是:当Rails应用程序运行时,是否有任何警告要在后台运行某种runloop?我从Objective-C / Java了解多线程的含义,但我要具体询问Rails(3)环境。
基本上类似于:
class SiteAlertsMap < Hash
include Singleton
def initialize
super
begin_polling
end
# ... SNIP, any specific methods etc ...
private
def begin_polling
# Create some other Thread here, which polls at set intervals
end
end
这引出了一个类似的问题。我们将(加密的)任务推送到SQS队列,用于与电子商务和长时间运行的后台任务相关的事务。我们不使用cron,而是使用PHP编写的worker守护进程,它在后台运行。现在,当我们部署时,我们必须关闭这个工作人员并从新的代码库再次启动它。在Rails中,我能以某种方式让这个过程开始和停止使用rails服务器(独角兽)本身吗?我不认为这是我在主进程中在一个单独的线程中运行的东西,因为我们经常希望将它作为一个进程单独控制,但如果它只是在Web应用程序运行时方便地运行会很好。
答案 0 :(得分:7)
对ruby中的后台进程进行线程处理将是一个可怕的错误,尤其是因为您使用的是多进程服务器。使用独角兽说4个工人进程意味着你要从他们每个人进行轮询,这不是你想要的。 Ruby并没有真正的线程,它在1.8中有绿色线程,在1.9 IIRC中有一个全局解释器锁。许多宝石和图书馆也是令人讨厌的不可思议的。
使用memcache仍然是您的最佳选择,如果您正确设置它,您应该只看到它在请求时添加一毫秒或两秒。另一个选项可以让您在保留最小额外开销的同时保留这些警报的好处是将这些警报存储在redis中。这样可以更好地保护您免受内存崩溃或服务器重启等事件的影响。
对于后台作业,您应该使用与现有类似的方法,但有几个现成的处理程序,如resque,delayed_job和其他一些。如果您绝对必须使用SQS作为后端队列,您可能能够找到一些代码来帮助您,但您可以自己编写它。这仍然需要在代码更改时重新启动其他守护程序。在实践中,这并不是一个大问题,因为最佳实践要求使用像capistrano这样的部署系统,其中可以轻松添加规则以在部署时退回守护程序。我使用monit来监视守护进程,所以重启它就像告诉monit重启它一样简单。
一般来说,Ruby在线程方面不像Java / Objective-C。它遵循更像Unix的基于流程的隔离模型,但社区已经提出了最佳实践和方法,使其比其他语言更少痛苦。 Ruby确实需要更多关注设置其堆栈,因为它不像启用mod_php
和复制一些文件那么简单,但是一旦了解了选择和架构,就可以更容易地推断出应用程序的工作原理。在我看来,流程模型对于Web应用程序要好得多,因为它将代码和状态与其他正在运行的操作的影响隔离开来。隔离还使应用程序更易于在分布式系统中使用。