是Rails的无共享,也可以单独的请求访问相同的运行时变量?(Is Rails shared-not

2019-06-23 19:58发布

PHP运行在无共享环境,在这种情况下意味着每一个Web请求是在清洁的环境中运行。 不能通过重复通过单独的持久层(文件系统,数据库等)访问另一请求的数据。

什么Ruby on Rails的? 我刚刚看了一篇博客文章中指出,单独的请求可能访问同一类变量。

它发生,我认为这可能取决于Web服务器上。 杂种的FAQ指出杂种使用每个请求一个线程-这表明无共享环境。 常见问题解答接着说,回报率不是线程安全的,这进一步表明,除非新的请求重新使用先前请求创建的内存中对象的回报率将不会在一个共享的环境中。

显然,这有着巨大的安全后果。 所以,我有两个问题:

  1. 是RoR的环境无共享?
  2. 如果回报率在运行(或可能在某些情况下运行)一个共享的环境,什么变量和其他数据存储,我应该偏执?

更新:我会进一步明确。 在Java Servlet容器,你可以拥有多个请求对象持久。 这通常是针对多个用户将有机会获得,数据库连接,等等高速缓存数据完成。在PHP这不能在应用层完成,它必须在一个单独的持久层等Memcached的来完成。 所以,双重问题是:哪些情形是一样的回报率(PHP或Java),如果像Java, 数据类型持续跨越多个请求?

Answer 1:

简而言之:

  1. 没有, 从来没有的Rails在无共享环境中运行。
  2. 偏执关于类变量类的实例变量

较长的版本:

Rails的过程通过加载框架和应用开始其生命周期。 他们通常只运行一个线程,将处理其一生中的许多要求。 该请求将因此受到严格按顺序发送。

然而,所有的类坚持跨请求。 这意味着不同请求之间共享从您的类和元类(如类变量和类的实例变量)引用的任何对象。 这可能会咬你 ,例如,如果你试图memoize的方法( @var ||= expensive_calculation在你的的方法),期待它只会在当前请求期间持续。 在现实中,计算将只在第一次请求执行。

从表面上看,它可能看起来很好的实现缓存,或其他行为取决于跨请求持久性。 通常情况下,事实并非如此。 这是因为大多数部署策略将使用几个 Rails的进程来对付自己的单线程性质。 它根本就没有冷却到阻止所有请求,同时等待一个缓慢的数据库查询,这样讨巧的产卵多个进程。 当然,这些进程不共享任何东西(除了一些记忆也许,你不会注意到)。 如果您的请求时在类变量或类的实例变量保存的东西,这可能会咬你 。 然后,不知何故,有时东西似乎是现在,有时它似乎消失了。 (在现实中,当然,数据可以或者可以不存在于一些过程 ,而在其他不存在)。

一些部署配置(最显着的JRuby + Glassfish的)其实都是多线程的。 Rails是线程安全的,因此它可以对付它。 但是你的应用程序可能不会是线程安全的。 所有控制器的情况下被扔掉每个请求后,但我们知道,这些类是共享的。 如果你在类变量或类的实例变量各地传递信息这可能会咬你 。 如果不正确地使用同步方法,你很可能在竞争状态地狱结束。


作为一个方面说明:滑轨一般是在单线程进程中运行,因为Ruby的线程实现太差劲了。 幸运的是,事情在Ruby 1.9的更好一点。 而很多 JRuby中更好。

与这两个Ruby实现普及开来,它很可能是多线程的Rails部署策略也将获得普及和数量。 这是编写多线程请求,考虑到调度已有的应用程序是个好主意。



Answer 2:

这里是说明,如果你不小心有关修改共享对象会发生什么一个相对简单的例子。

  1. 创建一个新的Rails项目: rails test

  2. 创建一个新文件lib/misc.rb ,并把它这样的:

     class Misc @xxx = 'Hello' def Misc.contents() return @xxx end end 
  3. 创建一个新的控制器: ruby script/generate controller Posts index
  4. 更改app/views/posts/index.html.erb包含以下代码:

     <% require 'misc'; y = Misc.contents() ; y << ' (goodbye) ' %> <pre><%= y %></pre> 

    (这是我们修改隐式共享对象)。

  5. 添加REST风格的路线, config/routes.rb
  6. 启动服务器ruby script/server并加载网页/posts几次。 你会看到数量( goodbye)弦上的每个连续的页面重载增加一个。


Answer 3:

在您使用平均客运部署,你可能有共享各自从请求之间保持它们的(静)态过程中的他们,但类之间没有多个应用程序的过程。 每个请求,但是,让你的控制器的新实例。

你可以把这种不同的共享状态环境的集群。

要使用您的Java比喻,你可以做缓存,并将它从请求之间的工作,你就不能认为这将是可在每次请求。



Answer 4:

无共享有时是一个好主意。 但是,当你还没有装入大型应用程序框架和大的领域模型,并在每个请求的大量配置。

为了提高效率,滑轨保持一些在存储器中可用的数据为应用程序的生命周期的所有请求之间共享。 大多数这类数据是只读的,所以你不应该担心。

当你写你的应用程序,从编写到共享对象(不包括数据库,例如,其散发出来的最盒具有良好的并发控制)走就走,你应该罚款。



文章来源: Is Rails shared-nothing or can separate requests access the same runtime variables?