Тайм-аут ActiveResource не работает

Я пытаюсь связаться с REST API, используя ActiveResource on Rails 2.3.2.

Я пытаюсь использовать функцию тайм-аута, чтобы, если ресурс, с которым я связываюсь, не работал, я мог быстро выйти из строя - я делаю это со следующим:

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

Однако, когда я пытаюсь связаться со службой, когда я знаю, что она недоступна, время ожидания класса истекает только через 60 секунд по умолчанию. Из стека ошибок я вижу, что ошибка тайм-аута действительно исходит от класса ActiveResource в моей папке gem, который имеет надлежащие функции для разрешения настроек тайм-аута, но мой установленный тайм-аут никогда не работает.

Есть предположения?


Так что, видимо, проблема не в том, что тайм-аут не работает. Я могу запустить сервер локально, заставить его не возвращать ответ в течение установленного времени ожидания и убедиться, что время ожидания работает.

Дело в том, что если сервер не принимает соединение, тайм-аут не работает так, как я ожидал, - он вообще не работает. Похоже, что тайм-аут работает только тогда, когда сервер принимает соединение, но слишком долго отвечает.

Для меня это кажется проблемой - не должен ли тайм-аут работать, когда сервер, с которым я связываюсь, не работает? Если нет, должен быть другой механизм, чтобы предотвратить зависание кучи запросов... кто-нибудь знает быстрый способ сделать это?


person Ben    schedule 16.07.2009    source источник


Ответы (2)


Проблема

Если вы используете Ruby 1.8.x, проблема заключается в отсутствии реальных системных потоков.

Как вы можете прочитать сначала здесьи то здесь есть системные проблемы с таймаутами в Ruby. Интересное обсуждение, но для вас, в частности, некоторые комментарии предполагают, что тайм-аут эффективно игнорируется и по умолчанию равен 60 секундам - ​​именно то, что вы видите.


Решения ...

У меня есть аналогичная проблема с нашим собственным продуктом при попытке отправить электронные письма - если почтовый сервер не работает, поток блокируется. Для меня решение заключалось в том, чтобы выделить запрос в отдельный поток, и поэтому мой основной поток обработки запросов не блокируется.

Существуют неблокирующие библиотеки для Ruby, но, возможно, вы могли бы сначала взглянуть на этот системный тайм-аут Gem.

Вариант, открытый для всех, кто использует Rails за прокси-сервером, таким как nginx, состоит в том, чтобы установить тайм-аут восходящего потока на меньшее число — таким образом вы получите уведомление, если сервер занимает слишком много времени. Я бы сделал это, только если бы я действительно застрял в решении.

И последнее, но не менее важное: возможно, запуск Rails 2.3.2 поверх Ruby 1.9.1 решит проблему.

person Chris McCauley    schedule 16.07.2009
comment
Спасибо за ответ - я использую 2.3.2 и не думаю, что проблема с потоками - см. мой комментарий ниже - person Ben; 16.07.2009

В качестве альтернативы вы можете попытаться отловить эти ошибки подключения и повторить попытку один раз (через определенный период времени), просто чтобы убедиться, что соединение действительно отсутствует.

      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

person Alex Kozlov    schedule 17.05.2017