在我的应用程序中,在homepage操作中,我调用了一个返回JSON的特定web服务。
parsed = JSON.parse(open("http://myservice").read)
@history = parsed['DATA']此数据不会每60秒更改一次,并且不会针对每个访问者进行更改,因此,理想情况下,我希望缓存@history变量本身(因为解析不会产生新的结果),如果它超过一分钟,则自动使其无效。
我不确定做这件事的最好方法。默认的Rails缓存方法似乎都更倾向于需要手动过期的内容。我相信有一个快速而简单的方法可以做到这一点,我只是不知道它是什么!
发布于 2011-08-30 16:36:35
您可以使用内置的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作业尚未运行,则第一个请求除外)。
发布于 2011-08-30 13:00:30
我不知道有什么简单易懂的方法可以做到这一点。你可能会考虑使用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进程。
发布于 2011-08-30 13:21:52
我们有一个类似的需求,我们最终使用Squid作为来自rails服务器的所有webservice调用的转发代理。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。
https://stackoverflow.com/questions/7238753
复制相似问题