0

我有一个 Rails 应用程序,每次执行搜索时都会从 .yml 文件中读取。(这是一个全文搜索应用程序。).yml 文件告诉应用程序它应该向哪个 url 发出搜索请求,因为不同版本的搜索索引驻留在不同的服务器上,我偶尔会在索引之间切换。

我有一个应用程序的管理部分,允许我重写上述 .yml 文件,以便我可以添加新的搜索 url 或删除不需要的。虽然我可以手动编辑服务器上的文件,但我更希望能够在我的站点管理部分中编辑它,这样当我无权访问服务器时,我仍然可以进行任何必要的更改。

对我的应用实际使用的文件进行编辑的最佳做法是什么?(我想这也适用于,比如说,一个能够在部署后重写自己的帮助文件的应用程序。)

当另一个连接到我的站点的用户想要执行搜索时,我可能正在重写此文件,这是否是一个问题?如果我正在进行写操作,我可以让他们的搜索失败吗?我应该最初将新的 .yml 文件写入临时文件,然后再替换原始的 .yml 文件吗?我知道写操作非常快,但我只是想看看其他人的想法。

更新:感谢大家的回复!虽然我发现我最好使用某种缓存而不是在每个请求上读取文件,但它有助于找出实际执行文件重写的最佳方法是什么,因为我特别希望重新- 在这种特定情况下每次都阅读它。

4

3 回答 3

2

如果您必须为此使用文件,则安全过程如下所示:

  1. 将新内容写入某种临时文件。
  2. 用于File.rename以原子方式将旧文件替换为新文件。

如果你不使用单独的文件,当不可避免的问题发生时,你很容易得到一个写一半的损坏文件。File.rename类方法只是系统调用的一个包装器,它rename(2)保证是原子的(即它要么完全成功,要么完全失败,它不会让你处于不一致的中间状态)。

如果你想替换,/some/path/f.yml那么你会做这样的事情:

begin
  # Write your new stuff to /some/path/f.yml.tmp here
  File.rename('/some/path/f.yml.tmp', '/some/path/f.yml')
rescue SystemCallError => e
  # Log an error, complain loudly, fall over and cry, ...
end

正如其他人所说,文件确实不是处理此问题的最佳方法,如果您有多个服务器,当服务器不同步时,使用文件将失败。您最好使用多个服务器可以访问的数据库,然后您可以:

  1. 缓存每个 Web 服务器进程中的值。
  2. 每 10 分钟(或任何可行的方法)盲目刷新一次。
  3. 如果连接到远程服务器失败,则刷新缓存值(使用额外的错误检查以避免刷新/连接/失败循环)。
于 2012-04-25T19:22:28.407 回答
1

如果您真的想通过覆盖文件来做到这一点,请使用文件系统的锁定功能来阻止其他线程在写入配置文件时访问您的配置文件。也许看看这样的东西

我强烈建议不要在不重新部署应用程序的情况下使用需要更改的配置文件。首先,您现在要求每次有人进行搜索时都读取一个文件。其次,出于安全原因,允许您的 Web 应用程序对其自己的代码进行写访问通常不是一个好主意。我会将这些搜索索引 URL 存储在数据库或 memcached 键中。

编辑:正如@bioneuralnet 指出的那样,重要的是决定您是需要实时配置更新还是最终同步。

于 2012-04-25T17:10:58.377 回答
1

首先,让我说在每个请求上读取该文件是性能杀手。不要这样做!如果您确实需要将该数据保存在 .yml 文件中,那么您需要缓存它并仅在它更改后重新加载(基于文件的时间戳)。

但是不要检查每个请求的时间戳 - 这几乎一样糟糕。如果自上次检查以来已经过了 n 分钟,请在请求中检查它。大概在before_filter某个地方。如果您在线程模式下运行(大多数人不是),请注意您使用的是 Mutex 或其他东西。

于 2012-04-25T17:15:52.617 回答