当前位置:  开发笔记 > 编程语言 > 正文

Rails是否共享 - 或者可以将请求分开访问相同的运行时变量?

如何解决《Rails是否共享-或者可以将请求分开访问相同的运行时变量?》经验,为你挑选了2个好方法。

PHP在无共享环境中运行,在这种情况下,这意味着每个Web请求都在一个干净的环境中运行.除了通过单独的持久层(文件系统,数据库等)之外,您无法访问其他请求的数据.

Ruby on Rails怎么样?我刚看了一篇博文,说明单独的请求可能会访问同一个类变量.

我想到这可能取决于Web服务器. Mongrel的FAQ说明Mongrel每个请求使用一个线程 - 建议无共享环境.FAQ继续说RoR不是线程安全的,这进一步表明RoR不会存在于共享环境中,除非新请求重用从先前请求创建的内存中对象.

显然这具有巨大的安全后果.所以我有两个问题:

    RoR环境是否共享?

    如果RoR在共享环境中运行(或者可能在某些情况下运行),那么我应该对哪些变量和其他数据存储感到偏执?

更新:我会进一步澄清. 在Java servlet容器中,您可以拥有跨多个请求持久化的对象.这通常用于缓存多个用户可以访问的数据,数据库连接等.在PHP中,这不能在应用程序层完成,它必须在像Memcached这样的单独的持久层中完成.因此,双重问题是:哪种情况是RoR(PHP或Java),如果像Java一样,哪些数据类型在多个请求中持续存在?



1> molf..:

简而言之:

    不,Rails 永远不会在无共享环境中运行.

    类变量类实例变量要偏执.

版本较长:

Rails进程通过加载框架和应用程序来开始其生命周期.它们通常只运行一个线程,它将在其生命周期内处理许多请求.因此,将严格按顺序发送请求.

尽管如此,所有类仍然存在于请求中.这意味着将从您的类和元类引用的任何对象(例如类变量和类实例变量)在请求之间共享.例如,如果您尝试在方法中记住methods(),期望它只会在当前请求期间保持不变,这可能会让您感到困惑.实际上,计算仅在第一次请求时执行.@var ||= expensive_calculation

从表面上看,实现缓存或依赖于跨请求持久性的其他行为似乎很不错.通常,它不是.这是因为大多数部署策略将使用多个 Rails进程来抵消它们自己的单线程特性.在等待慢速数据库查询时阻塞所有请求根本不是很酷,因此最简单的方法是生成更多进程.当然,这些过程并不共享任何东西(除了一些内存,你可能不会注意到).如果您在请求期间保存类变量或类实例变量中的内容,这可能会让您感到困惑.然后,不知何故,有时候东西似乎存在,有时它似乎消失了.(实际上,当然,数据在某些过程中可能存在也可能不存在,而在其他过程中则不存在).

一些部署配置(最显着的JRuby + Glassfish的)实际上多线程.Rails是线程安全的,所以它可以处理它.但您的应用程序可能不是线程安全的.每次请求后都会抛弃所有控制器实例,但正如我们所知,这些类是共享的.如果您在类变量或类实例变量中传递信息,这可能会让您感到困惑.如果你没有正确使用同步方法,你很可能最终处于竞争状态地狱.


作为旁注:Rails通常在单线程进程中运行,因为Ruby的线程实现很糟糕.幸运的是,Ruby 1.9中的情况要好一些.和很多 JRuby中更好.

随着这些Ruby实现越来越受欢迎,似乎多线程Rails部署策略也将获得普及和数量.最好在编写具有多线程请求调度的应用程序时考虑到这一点.


感谢优秀的回复molf,最有帮助.对于Ruby新手,类变量是静态类变量,如@@ bar.类实例变量是常规实例变量(@bar),但在静态类上下文中使用.例如:def foo {p @bar}打印一个常规对象实例变量,其中def self.foo {p @bar}打印一个类实例变量.这是因为Ruby中的所有东西都是一个对象,包括一个静态类.所以静态类对象可以有实例变量.我是Ruby的新手,所以如果我错了,请告诉我,我会发一个新问题.:)

2> rlandster..:

这是一个相对简单的示例,说明了如果您不小心修改共享对象会发生什么.

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

    创建一个新文件lib/misc.rb并输入:

    class Misc
      @xxx = 'Hello'
      def Misc.contents()
        return @xxx
      end
    end
    

    创建一个新的控制器: ruby script/generate controller Posts index

    更改app/views/posts/index.html.erb以包含此代码:

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

    (这是我们修改隐式共享对象的地方.)

    添加RESTful路由到config/routes.rb.

    启动服务器ruby script/server/posts多次加载页面.您将看到( goodbye)每个连续页面重新加载时字符串的数量增加1.

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有