在Ruby on Rails中,如何在会话之间将对象保留在内存中

我正在尝试构建一些东西(最终是一个gem,但现在是一个应用程序),其工作方式如下。

例如,假设DB记录是狗的品种。 每个品种都有一个Dog父类和一个子类。 直到运行时才知道实际品种。

当服务器开始时,它将从DB加载记录并根据记录实例化类的实例,例如,我可能有两个小猎犬和贵宾犬。 当有人来到服务器时,他们可能想要访问其中一个狗实例。

为什么不动态创建实例? 在我的例子中,“狗”基本上是包含算法和数据的类。 该算法没有改变,数据很少改变(大约几天),但是算法本身的执行,其使用数据和传递的一些动态数据,例如时间戳,将被访问多次。

如果必须重新创建对象的实例并且每次只是为了在下一个请求上再次执行请求而加载数据(请求不会更改对象的状态),那将是愚蠢的。 当我可以重复使用同一个对象时,我会创建并销毁多个对象。

将它保留在会话中是没有意义的,因为想要一个贵宾犬的人不需要在她的会话对象中有beagles信息; 这是无关紧要的(并且没有规模)。

如何将这些对象保存在内存中? 我基本上想要一个查找表来保存实例。 在Java中,我将使用某种类型的hashmap或数组创建一个单例,它位于内存中。 在rails中我通过在lib文件夹中创建一个单例类来尝试这个。 我认为 – 我可能不理解这一点 – 当会话消失时,实例(事实上它是单身人士没有实际意义)正在丢失。

我找到的最接近的答案是http://www.ruby-forum.com/topic/129372 ,它基本上将所有内容放在课程领域和方法中。 不知怎的,这似乎不对。

TIA!

另外:我来自Java。 在Java中,我只是创建一个位于堆上或者可能位于JNDI树中的对象,当HTTP请求进入时,它们将由一个servlet或EJB或一些每个请求项处理,然后可以访问持久对象。 我似乎无法在rails中找到相应的东西。

也许你的例子很简单。 我假设您的对象非常复杂,并且您的基准测试显示构建它们对于每个请求都是不合理的。

在生产模式下,不会在请求之间卸载类,但是这些类的实例是。 因此,使用class级的class级成员听起来像是找我的方式。 只需使用它来存储您的实例。

class ObjectCache @@objects = {:beagle => Beagle.new, :poodle => Poodle.new} def lookup key @@objects[key.to_sym] end end 

我不会过分担心加载和丢弃对象,除非你能提出一个certificate它是一个问题的基准。 当然,每个请求都会创建大量的中间对象,这些通常在几毫秒内创建和销毁。

通常最好只关注仅加载所需内容,对数据库进行反规范化以将频繁访问的数据或方法推送到方便的位置,或者将复杂计算的结果保存在缓存字段中。

基准测试,仅在需要时进行优化。

将模型实例保存到类高​​速缓存可以起作用,但它只是生产环境中的一个选项,其中模型类不会随每个请求重新加载。 它还会使您遇到由陈旧数据引起的错误。

如果您有使用这些方法无法解决的扩展问题,您可能需要使用Rack和EventMachine的组合来研究为部分function构建持久性服务器。 有许多方法可以构建可以使用预先加载的数据集执行复杂计算的后台进程,但具体方法取决于几个因素,例如您正在使用的数据类型以及频率它将被访问。

在生产中,控制器和模型类不会在请求之间重新加载,因此您有以下几种选择:

  • 在application_controller中将对象设置为类变量
  • 在模型类本身中创建返回值的单例方法

是的,也可以防止类在开发模式下卸载。 这不仅仅是一种生产模式。 虽然默认情况下在生产模式下发生,但您必须在开发模式下手动设置它。

为了不在每个请求上重新加载您的类,即使在开发模式下,您也可以将它们移动到自动加载路径之外的某个位置(如果使用app和lib目录之外的默认值)。 这样,您可以在请求之间保留这些对象类,从而使用它们来存储对于每个请求都相同的数据。