阻塞IO / Ruby on Rails

12

我正在考虑使用Rails编写一个web应用程序。用户发出的每个请求都依赖于调用外部API。这个外部API可能会随机变得非常慢(2-3秒),显然这会影响到单个请求。

在代码等待外部API返回的时间内,是否会阻塞进一步的用户请求?

只是为了进一步澄清,因为似乎有些混淆,这是我预期的模型:

  1. Alice向我的Web应用程序发出请求。为了满足这个请求,需要调用API服务器A。API服务器A很慢,需要3秒钟才能完成。
  2. 在这个等待时间里,当Rails应用程序调用API服务器A时,Bob发出了一个请求,该请求必须向API服务器B发出请求。

Ruby解释器(或者Rails 3.x框架中的某些东西)是否会阻塞Bob的请求,要求他等到Alice的请求完成后再进行处理?


我其实有类似的问题..但我只是想知道,你是通过ActiveRecord从Rails应用程序中进行数据库查询,还是数据纯粹由后端API服务器驱动,该服务器进行数据库查询并将结果返回给你的Rails前端? - Benny Tjia
@BennyTjia 两者都有。单个请求将使用本地存储的数据和API服务器返回的唯一数据。 - Matty
3个回答

8

如果您只使用一个单线程、非事件驱动的服务器(或不使用事件驱动 I/O 与事件驱动服务器),是的。其他解决方案,如使用 ThinEM-Synchrony 将避免此问题。

详细说明,基于您的更新:

不,Ruby 和 Rails 都不会导致您的应用程序阻塞。但您忽略了会导致阻塞的部分:Web 服务器。您需要多个进程、多个线程或一个事件驱动服务器,并使用事件驱动 I/O 库进行 Web 服务请求。

@alexd 描述了使用多个进程。我个人更喜欢事件驱动服务器,因为我不需要事先知道/猜测可能有多少并发请求(或使用根据负载启动进程的东西)。单个 nginx 进程作为前端,单个 thin 进程可以处理大量并行请求。


3
网络延迟?如果您的意思是当前用户将被迫等待,那当然会发生(但我认为从提问者的方式来看,这是不可避免的)。我理解这个问题不是关于如何避免外部服务对用户造成延迟的,而是阻塞其他并发请求。 - smparkes
@smparkes 我在有关此事的问题中添加了进一步的澄清。 - Matty

3
你的问题的答案取决于你的Rails应用程序运行在哪个服务器上。你现在使用什么?Thin?Unicorn?Apache+Passenger?
我完全推荐Unicorn适合你的情况——它使得并行运行多个服务器进程非常容易,并且你可以通过更改配置文件中的一个数字来配置并行进程的数量。当一个Unicorn worker处理Alice的高延迟请求时,另一个Unicorn worker可以利用你的空闲CPU周期处理Bob的请求。

0
很可能是这样的。当然,有绕过此问题的方法,但没有一种方法是简单的。
更好的问题是,为什么您需要在每个请求上调用外部API?为什么不在Rails应用程序和外部API之间实现缓存层,并将其用于大多数请求?
这样,通过一些自定义逻辑来使缓存过期,您将拥有一个快速的Rails应用程序,并仍能利用外部API服务。

返回的数据会随着每个请求而改变,因此无法进行缓存。 - Matty
所以,你的意思是你的API就是你的数据库?这在长期来看似乎不可行... - Srdjan Pejic
API并不像数据库一样运作。 - Matty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接