为什么Rails动作控制器不使用线程?

时间:2013-04-01 00:56:59

标签: ruby-on-rails ruby multithreading actioncontroller

My Rails应用程序的路由需要花费大量时间才能处理,这会使整个网页冻结。

  1. 为什么会这样?是Rails还是非线程安全的第三方宝石?
  2. 有什么方法可以解决这个问题吗?我正在考虑使用一个进程池,就像一个线程池,除了它更重,它会占用大量内存,但它比停止整个应用程序要便宜。

2 个答案:

答案 0 :(得分:2)

Rails在中间件堆栈中围绕整个请求使用互斥锁,因此Rails进程一次只能接受一个请求。

但是,您可以通过启用config.threadsafe!选项并使用多线程服务器(例如Puma)来禁用此功能。

然后有使用MRI的整个障碍,除非他们正在进行非阻塞I / O,否则不会让两个线程同时运行。

您需要使用支持真实线程的Ruby实现,例如Rubinius或Jruby。

答案 1 :(得分:2)

首先要注意的是,你的Rails动作不应该是重量级的。当用户请求页面时,您应该立即为用户提供服务。

现在,有些情况下您需要用户等待结果,在这种情况下,您始终可以使用websockets或HTTP streaming

现在,Ruby和Rails存在线程问题,您可以在“Parallelism is a Myth in Ruby”中阅读。

您可以在Rails中使用的解决方案是使用像Unicorn这样的服务器,它可以根据需要分配多个流程工作者,并且每个服务器将独立于其他服务器工作,Puma用于创建多线程等等。

现在,如果您的操作过程很繁重,您可能希望将工作延迟到像delayed_job这样的流程池。您甚至可以使用JavaScript创建一个漂亮的UI来获取作业的状态并向用户显示进度。您可以使用RabbitMQ执行任务池,其中另一个进程在后台可以侦听新消息并对其进行操作,甚至可以给出响应等。

请记住,大多数网络服务器都有客户端超时,并且你真的不希望用户在没有响应的情况下等待一分钟或更长时间,所以使用流响应来立即提供一些反馈总是很好的操作正在完成,或者使用一些JavaScript代码回答,这些代码将继续命中服务器以查看任务的执行方式,甚至是必要的websocket。