Rails 3 - 缓存Web服务调用

时间:2011-08-30 04:35:42

标签: ruby-on-rails-3 web-services caching

在我的应用程序中,在主页操作中,我调用了一个返回JSON的特定Web服务。

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

此数据每60秒不会更改多次,并且不会因每个访问者而改变,所以我希望理想情况下缓存@history变量本身(因为解析不会导致一个新结果)如果超过一分钟,则自动使其失效。

我不确定这样做的最好方法。默认的Rails缓存方法似乎都更倾向于需要手动过期的内容。我确信有一种快速简便的方法可以做到这一点,我只是不知道它是什么!

3 个答案:

答案 0 :(得分:6)

您可以使用内置的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方法以避免此问题。阅读更多相关信息here

以前版本的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 :(得分:1)

我不知道这样做的简单方法。您可能想要研究使用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进程。

答案 2 :(得分:0)