ActiveResource 超时不起作用

发布于 2024-07-26 16:53:09 字数 672 浏览 2 评论 0原文

我正在尝试使用 Rails 2.3.2 上的 ActiveResource 联系 REST API。

我正在尝试使用超时功能,这样如果我正在联系的资源已关闭,我可能会很快失败 - 我正在通过以下方式执行此操作:

class WorkspaceResource < ActiveResource::Base
  self.timeout = 5
  self.site = "http://mysite.com/restAPI"
end

但是,当我尝试联系该服务时,我知道它没有关闭可用,该类仅在默认 60 秒后超时。 我可以从错误堆栈中看到,超时错误确实来自我的 gem 文件夹中的 ActiveResource 类,该类具有允许超时设置的适当功能,但我设置的超时似乎从未起作用。

有什么想法吗?


所以显然问题不在于超时不起作用。 我可以在本地运行服务器,使其在超时限制内不返回响应,并查看超时是否有效。

事实上,问题在于,如果服务器不接受连接,超时就不会像我预期的那样发挥作用 - 它根本不起作用。 看起来超时仅在服务器接受连接但响应时间过长时才起作用。

对我来说,这似乎是一个问题 - 当我联系的服务器关闭时,超时不应该也起作用吗? 如果没有,应该有另一种机制来阻止一堆请求挂起......有人知道快速的方法来做到这一点吗?

I'm trying to contact a REST API using ActiveResource on Rails 2.3.2.

I'm attempting to use the timeout functionality so that if the resource I'm contacting is down I can fail quickly - I'm doing this with the following:

class WorkspaceResource < ActiveResource::Base
  self.timeout = 5
  self.site = "http://mysite.com/restAPI"
end

However, when I try to contact the service when I know it isn't available, the class only times out after the default 60 seconds. I can see from the error stack that the timeout error does indeed come from an ActiveResource class in my gem folder that has the proper functions to allow timeout settings, but my set timeout never seems to work.

Any thoughts?


So apparently the issue is not that timeout is not functioning. I can run a server locally, make it not return a response within the timeout limit, and see that timeout works.

The issue is in fact that if the server does not accept the connection, timeout does not function as I expected it to - it doesn't function at all. It appears as though timeout only works when the server accepts the connection but takes too long to respond.

To me, this seems like an issue - shouldn't timeout also work when the server I'm contacting is down? If not, there should be another mechanism to stop a bunch of requests from hanging...anyone know of a quick way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清晰传感 2024-08-02 16:53:09

问题

如果您在 Ruby 1.8.x 上运行,那么问题就在于它缺少真正的系统线程。

正如您可以阅读首先在这里然后这里,Ruby 中存在系统超时问题。 这是一个有趣的讨论,但对您来说尤其如此,一些评论表明超时实际上被忽略并默认为 60 秒 - 正是您所看到的。

解决方案...

在尝试发送电子邮件时,我对我们自己的产品也有类似的问题 - 如果电子邮件服务器出现线程阻塞。 对我来说,解决方案是将请求分离到单独的线程上,因此我的主请求处理线程不会阻塞。

Ruby 有一些非阻塞库,但也许您可以先看看这个 System Timeout Gem

任何在 nginx 等代理后面使用 Rails 的人都可以选择将上游超时设置为较低的数字 - 这样,如果服务器花费的时间太长,您就会收到通知。 只有当我真的找不到解决方案时我才会这样做。

最后但并非最不重要的一点是,在 Ruby 1.9.1 之上运行 Rails 2.3.2 可能会解决该问题。

The problem

If you're running on Ruby 1.8.x then the problem is its lack of real system threads.

As you can read first hereand then here, there are systemic problems with timeouts in Ruby. An interesting discussion but for you in particular some comments suggest that the timeout is effectively ignored and defaults to 60 seconds - exactly what you are seeing.

Solutions ...

I have a similar issue with our own product when trying to send emails - if the email server is down the thread blocks. For me the solution was to spin the request off on a separate thread and therefore my main request-processing thread doesn't block.

There are non-blocking libraries out there for Ruby but perhaps you could take a look first at this System Timeout Gem.

An option open to anyone using Rails behind a proxy like nginx would be to set the upstream timeout to a lower number - that way you'll get notified if the server is taking too long. I'd only do this if I were really stuck for a solution.

Last but not least, it's possible that running Rails 2.3.2 on top of Ruby 1.9.1 will fix the issue.

虚拟世界 2024-08-02 16:53:09

或者,您可以尝试捕获这些连接错误并重试一次(在一段时间后),以确保连接确实已断开。

      retried = false
      begin
        @businesses = Business.find(:all, :params => { :shop_domain => @shop.domain })
        retried = false
      rescue ActiveResource::TimeoutError => ex          

      #raise ex

      rescue ActiveResource::ConnectionError, ActiveResource::ServerError, ActiveResource::ClientError => ex
        unless retried           
          sleep(((ex.respond_to?(:response) && ex.response['Retry-After']) || 5).to_i)
          retried = true             
          retry
        else              
          # raise ex
        end
      end

受到 Shopify 这个用于对大量记录进行分页的解决方案的启发。 https://ecommerce.shopify。 com/c/shopify-apis-and-technology/t/paginate-api-results-113066

Alternatively, you could try to catch these connection errors and retry once (after certain period of time) just to make sure the connection is really out.

      retried = false
      begin
        @businesses = Business.find(:all, :params => { :shop_domain => @shop.domain })
        retried = false
      rescue ActiveResource::TimeoutError => ex          

      #raise ex

      rescue ActiveResource::ConnectionError, ActiveResource::ServerError, ActiveResource::ClientError => ex
        unless retried           
          sleep(((ex.respond_to?(:response) && ex.response['Retry-After']) || 5).to_i)
          retried = true             
          retry
        else              
          # raise ex
        end
      end

Inspired by this solution from Shopify for paginating a large number of records. https://ecommerce.shopify.com/c/shopify-apis-and-technology/t/paginate-api-results-113066

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文