Rails 3 - кеш вызова веб-сервиса - PullRequest
6 голосов
/ 30 августа 2011

В моем приложении в действии домашней страницы я вызываю определенную веб-службу, которая возвращает JSON.

parsed = JSON.parse(open("http://myservice").read)
@history = parsed['DATA']

Эти данные не изменяются чаще, чем один раз в 60 секунд, и не изменяются в течение определенного периода времени.на основе посетителя, поэтому я хотел бы, в идеале, кэшировать саму переменную @history (поскольку синтаксический анализ не приведет к новому результату) и автоматически аннулировать ее, если она старше минуты.

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

Ответы [ 3 ]

6 голосов
/ 30 августа 2011

Для этого вы можете использовать встроенный кеш Rails:

@history = Rails.cache.fetch('parsed_myservice_data', :expires_in => 1.minute) do
  JSON.parse connector.get_response("http://myservice")
end

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

РЕДАКТИРОВАНИЕ: В Rails 3.x вы можете передать параметр :race_condition_ttl методу fetch, чтобы избежать этой проблемы. Подробнее об этом здесь .

Хорошим решением этой проблемы в предыдущих версиях Rails является настройка фонового задания / cron, которое будет запускаться через регулярные промежутки времени, которое будет извлекать и анализировать данные и обновлять кэш.

В вашем контроллере или модели:

@history = Rails.cache.fetch('parsed_myservice_data') do
  JSON.parse connector.get_response("http://myservice")
end

На вашем задании / cron:

Rails.cache.write('parsed_myservice_data',
  JSON.parse connector.get_response("http://myservice"))

Таким образом, ваши клиентские запросы всегда будут получать свежие кэшированные данные (за исключением первого запросить, если фоновое задание / cron еще не выполнено.)

1 голос
/ 30 августа 2011

Я не знаю легкого безрассудного способа сделать это. Возможно, вы захотите изучить использование Redis. Redis позволяет вам установить срок действия данных, которые вы в нем храните. В зависимости от того, какой Redis Gem вы используете, он будет выглядеть примерно так:

@history = $redis.get('history')

if not @history
  @history = JSON.parse(open("http://myservice").read)['DATA']
  $redis.set('history', @history)
  $redis.expire('history', 60)
end

Поскольку существует только одна служба redis, она будет работать для всех ваших процессов rails.

0 голосов
/ 30 августа 2011

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

http_connection_factory.rb:

class HttpConnectionFactory
  def self.connection
    AppConfig.use_forward_proxy ? Net::HTTP::Proxy(AppConfig.forward_proxy_host, AppConfig.forward_proxy_port) : Net::HTTP
  end
end

В действии домашней страницы вашего приложения вы можете использоватьпрокси вместо прямого вызова.

connector = HttpConnectionFactory.connection 
parsed = JSON.parse(connector.get_response("http://myservice"))
@history = parsed['DATA']

Мы подумали об использовании Redis или Memcache.Но у нас было несколько обращений в службу поддержки, и мы хотели избежать всех проблем, связанных с генерацией ключей и их очисткой в ​​подходящее время.

Итак, в нашем случае, прямой прокси позаботился обо всех этих мелочах.Пожалуйста, обратитесь к Squid Wiki для необходимых параметров конфигурации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...