【问题标题】:Using Puma and Sidekiq in a backend Rails app在后端 Rails 应用程序中使用 Puma 和 Sidekiq
【发布时间】:2013-10-04 20:11:31
【问题描述】:

我有一个带有Sidekiq 的后端Rails 服务器,它用作API 服务器。该应用程序的工作原理如下:

  1. 我的 Rails 服务器同时接收来自传入 API 客户端的许多请求。

  2. 对于这些请求中的每一个,Rails 服务器都会将作业分配给 Sidekiq 服务器。 Sidekiq 服务器向外部 API(如 Facebook)发出请求以获取数据,并对其进行分析并将结果返回给 Rails 服务器。

例如,如果我从我的 API 客户端收到 10 个传入请求,对于每个请求,我需要向外部 API 服务器发出 10 个请求,获取数据并进行处理。

我的挑战是让我的应用同时响应传入的请求。也就是说,对于每个传入的请求,我的应用程序应该并行处理:调用外部 API、获取数据并返回结果。

现在,我知道 Puma 可以为 Rails 应用程序添加并发性,而 Sidekiq 是多线程的。

我的问题是:如果我已经拥有 Puma,我真的需要 Sidekiq 吗?同时使用 Puma 和 Sidekiq 有什么好处?

特别是,对于 Puma,我只需从我的 Rails 应用程序调用我的外部 API 调用、数据处理等,它们将自动并发。

【问题讨论】:

    标签: ruby-on-rails sidekiq puma


    【解决方案1】:

    是的,您可能确实想使用 Puma 和 Sidekiq。这里真的有两个问题在起作用。

    并发(您似乎已经知道)是可以同时处理的 Web 请求的数量。使用像 Puma 或 Unicorn 这样的应用服务器肯定会帮助您获得比默认的 Web 砖服务器更好的并发性。

    另一个问题是服务器处理网络请求所花费的时间。

    这两件事相关的原因是,您的应用每秒可以处理的请求数是每个请求的平均处理时间和接受请求的工作进程数的函数。假设您的平均响应时间为 100 毫秒。然后一个 web worker 每秒可以处理 10 个请求。如果您有 5 个工作人员,那么您每秒可以处理 50 个请求。如果您的平均响应时间为 500 毫秒,那么您可以在单个工作人员的情况下处理 2 个请求/秒,在 5 个工作人员的情况下处理 10 个请求/秒。

    与外部 API 的交互有时会很慢,在最坏的情况下,远程端的服务器无响应或网络中断或速度变慢时,它可能非常不可靠。 Sidekiq 是将您的应用程序(和您的最终用户)与远程 API 响应缓慢的可能性隔离开来的好方法。想象一下,远程 API 由于某种原因运行缓慢,并且它的平均响应时间已减慢到每个请求 2 秒。在这种情况下,您只能处理 5 个工作人员的 2.5 个请求/秒。如果流量超过了您的最终用户可能会开始等待很长时间才能响应您的应用程序上的任何页面,即使是那些不进行远程 API 调用的页面,因为您的所有网络工作者可能都在等待缓慢的远程 API回复。随着流量的不断增加,您的用户将开始出现连接超时。

    使用 Sidekiq 的想法是将等待外部 API 的时间与 Web Worker 分开。您基本上会从您的用户那里获取数据请求,将其传递给 Sidekiq,然后立即向用户返回一个基本上说“我们正在处理您的请求”的响应。 Sidekiq 然后可以接手工作并提出外部请求。获得数据后,它可以将该数据保存回您的应用程序。然后,您可以使用 Web 套接字向用户推送数据准备就绪的通知。甚至直接将数据推送给他们并相应地更新页面。 (您也可以使用轮询让页面不断询问“准备好了吗?”,但这很快就会变得非常低效。)

    我希望这是有道理的。如果您有任何问题,请告诉我。

    【讨论】:

    • 非常感谢,杰里米。这很有道理。我的过程需要一到两分钟才能从外部 API 中提取数据。我担心的是,在等待来自 API 的数据时,我的工作人员的资源被锁定了。 Sidekiq 能帮我解决这个问题吗?
    • 是的,Sidekiq 会提供帮助。我的回答的最后一段很长的一段描述了它是如何工作的。
    • 谢谢杰里米。我得到了那部分。我的问题是:即使我的 Sidekiq 创建了多个线程并等待来自外部 API 的响应,这些线程在等待时是否仍会占用资源(CPU、RAM)几分钟?我推测如果我的应用程序可以异步运行,那么在等待响应时,我的服务器资源可以用于发出其他请求,或者处理从早期请求返回的数据。
    • 这个问题的答案很大程度上取决于外部 API 调用的工作方式。如果您可以向他们发出请求,然后他们立即返回“我们正在处理您的请求”消息,然后他们 POST 将结果发送到您端的网络挂钩,那么是的,您应该能够做其他等待时的事情。如果您发送一个请求并且他们的服务阻塞,直到它有数据准备好直接返回到同一个请求,那么您的工作人员在等待时仍然会消耗资源。
    【解决方案2】:

    Sidekiq 与 Resque 和 Delayed Job 一样,旨在提供来自队列的异步作业处理。

    如果您不需要将作业排队并异步运行,那么使用 Sidekiq 并没有实质性的好处(或坏处)。

    如果任务需要同步运行(听起来您可能会这样做——不清楚客户端是在等待数据还是只是请求作业运行),Sidekiq 及其相关工具可能是该作业的错误工具。使用 Sidekiq 或其他解决方案时无法保证处理时间;作业被推到堆栈的末尾,无论它可能有多长,并且在轮到它们之前不会被处理。如果客户端正在等待数据,他们可能会在您的工作池处理他们的工作之前 long 超时。

    【讨论】:

    • 谢谢@colinm。我的客户正在等待数据。通常,我的工作人员需要几分钟才能将结果返回给客户。但是,客户端可以一次发送多个请求。我想并行启动每个请求的数据处理,并将从我的 Sidekiq 服务器返回的任何内容返回给客户端。对于我的情况,什么是好的解决方案?谢谢你的洞察力。
    • 超过 750 毫秒?异步。
    猜你喜欢
    • 1970-01-01
    • 2016-02-10
    • 2016-04-20
    • 2017-03-08
    • 2014-09-07
    • 1970-01-01
    • 2018-11-19
    • 2016-10-10
    • 2018-01-30
    相关资源
    最近更新 更多