Ruby 在Sinatra中缓存文本文件内容
我不熟悉Sinatra和网络编程,所以使用的一些术语可能不太正确。无论如何 我有一个应用程序,它将.txt逐行读取到数组中,然后当你加载index.html.erb时,它会随机显示其中一行。我把内容放在一个文本文件中,而不是直接放在一个数组中,这样如果我需要添加更多的数据,那么更新就更容易了,然后直接添加到数组并重新部署应用程序。我关心的是,它是否正在重新创建数组,并在每次加载页面时重新读取文件。我不知道这种东西在服务器端是如何工作的,也不知道如何检查它。创建数组的代码如下所示:Ruby 在Sinatra中缓存文本文件内容,ruby,caching,sinatra,Ruby,Caching,Sinatra,我不熟悉Sinatra和网络编程,所以使用的一些术语可能不太正确。无论如何 我有一个应用程序,它将.txt逐行读取到数组中,然后当你加载index.html.erb时,它会随机显示其中一行。我把内容放在一个文本文件中,而不是直接放在一个数组中,这样如果我需要添加更多的数据,那么更新就更容易了,然后直接添加到数组并重新部署应用程序。我关心的是,它是否正在重新创建数组,并在每次加载页面时重新读取文件。我不知道这种东西在服务器端是如何工作的,也不知道如何检查它。创建数组的代码如下所示: before
before do
@ways ||= ['']
if @ways[1].nil?
File.open('ways.txt', 'r').each_line { |line| @ways << line }
end
end
有没有办法确保这是尽可能有效的?还是应该完全用另一种方式?根据Chrome开发工具,它每页传输约800b的负载。您在这里写的内容确实会在每次请求时将文件读取到一个数组中 提示:使用
@ways=File.readlines('ways.txt')
如果要缓存此阵列,可以在应用程序启动时将其作为常量进行缓存,例如:
WAYS = File.readlines('ways.txt').map(&:chomp)
get "/" do
@way = WAYS.sample
erb :index
end
但是,如果编辑了文本文件,则需要退出并重新启动服务器。如果您想避免这种情况,可以在操作之前检查中文件的修改时间,并且仅在内容发生更改时更新数组(replace
it)
如果你需要最后一个建议的帮助,请告诉我,我可以根据需要进行编辑
编辑:这里有一种方法可以使用常量保存数据并仅在文件更改时重新加载:
WAYS = { file:'ways.txt', all:[] }
before do
if WAYS[:updated] != (mtime=File.mtime(WAYS[:file]))
WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
WAYS[:updated] = mtime
end
end
get "/" do
@way = WAYS[:all].sample
erb :index
end
这对于检查每个请求的文件修改时间来说有点过分,但是对于负载最重或速度最慢的磁盘以外的所有磁盘,性能都应该良好
另一种解决方案是启动线程,每隔几分钟强制检查/更新阵列,例如
require 'sinatra'
WAYS = { file:'ways.txt', all:[] }
Thread.new do
loop do
if WAYS[:updated] != (mtime= File.mtime(WAYS[:file]))
WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
WAYS[:updated] = mtime
end
sleep 5 # seconds
end
end
get '/' do
WAYS[:all].sample
end
您在这里所写的内容确实会在每次请求时将文件读入一个数组
提示:使用@ways=File.readlines('ways.txt')
如果要缓存此阵列,可以在应用程序启动时将其作为常量进行缓存,例如:
WAYS = File.readlines('ways.txt').map(&:chomp)
get "/" do
@way = WAYS.sample
erb :index
end
但是,如果编辑了文本文件,则需要退出并重新启动服务器。如果您想避免这种情况,可以在操作之前检查中文件的修改时间,并且仅在内容发生更改时更新数组(replace
it)
如果你需要最后一个建议的帮助,请告诉我,我可以根据需要进行编辑
编辑:这里有一种方法可以使用常量保存数据并仅在文件更改时重新加载:
WAYS = { file:'ways.txt', all:[] }
before do
if WAYS[:updated] != (mtime=File.mtime(WAYS[:file]))
WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
WAYS[:updated] = mtime
end
end
get "/" do
@way = WAYS[:all].sample
erb :index
end
这对于检查每个请求的文件修改时间来说有点过分,但是对于负载最重或速度最慢的磁盘以外的所有磁盘,性能都应该良好
另一种解决方案是启动线程,每隔几分钟强制检查/更新阵列,例如
require 'sinatra'
WAYS = { file:'ways.txt', all:[] }
Thread.new do
loop do
if WAYS[:updated] != (mtime= File.mtime(WAYS[:file]))
WAYS[:all].replace File.readlines(WAYS[:file]).map(&:chomp)
WAYS[:updated] = mtime
end
sleep 5 # seconds
end
end
get '/' do
WAYS[:all].sample
end
提示:要获取随机数组元素,请使用@ways.sample
。提示:要获取随机数组元素,请使用@ways.sample
。我理解您的意思,但如果您能充实一下,我将不胜感激。这太棒了!你给了我很多东西要读。非常感谢!这是完全实用的。我有一个web应用程序,它使用线程(a)一次睡眠5分钟(在发送排队的电子邮件之间)和(b)一次睡眠24小时(使用每天一次的快照更新数据库中的非规范化统计表)。@thekungfuman No,实例变量特定于一个请求;您需要一个跨请求soops持久化的数据结构!我打错了。固定的。我对答案进行了编辑,以包含一个在本地适用的完整独立示例(已测试)。我理解您的意思,但如果您能充实一下,我将不胜感激。这太棒了!你给了我很多东西要读。非常感谢!这是完全实用的。我有一个web应用程序,它使用线程(a)一次睡眠5分钟(在发送排队的电子邮件之间)和(b)一次睡眠24小时(使用每天一次的快照更新数据库中的非规范化统计表)。@thekungfuman No,实例变量特定于一个请求;您需要一个跨请求soops持久化的数据结构!我打错了。固定的。我对答案进行了编辑,以包含一个在本地适用的完整独立示例(已测试)。