0

我的 Rails 应用程序有一个需要花费大量时间处理的路由,这使得整个网页冻结。

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

2 回答 2

2

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

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

然后是使用 MRI 的整个障碍,它不会真正让两个线程同时运行,除非它们正在执行非阻塞 I/O。

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

于 2013-04-01T01:15:28.627 回答
2

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

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

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

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

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

请记住,大多数网络服务器都有客户端超时,并且您真的不希望用户等待一分钟或更长时间而没有响应,因此使用流响应在操作时立即提供一些反馈总是很好的正在完成,或者用一些 JavaScript 代码回答,这些代码将继续访问服务器以查看任务是如何执行的,如果需要,甚至可以使用 websocket。

于 2013-04-01T01:20:34.663 回答