2013-10-04 16 views
1

我正在创建一个非常简单的基于机架的应用程序,因为我希望它可以执行非常特定的任务。在基于机架的应用程序中为每个HTTP请求创建新的控制器实例还是使用相同的实例更好?

server.rb看起来是这样的:

Path= File.expand_path("#{File.dirname __FILE__}/../../") 

require "bundler/setup" 
require "thin" 
require "rack" 

%w(parser auth controller).each do |file| 
    require "#{Path}/app/server/#{file}.rb" 
end 


builder = Rack::Builder.app do 
    use Auth 
    run Parser.new  
end 

Rack::Handler::Thin.run(builder, :Port => 8080, :threaded => true) 

parser.rb样子:

class Parser 

    def initialize 
    @controller = Controller.new 
    end 

    def call(env) 
    req = Rack::Request.new(env).params 
    res = Rack::Response.new 
    res['Content-Type'] = "text/plain" 

    command= req[:command] 

    if command =~ /\A(register|r|subscribe|s)\z/i 
     @controller.register  
    end 


    res.write command 
    res.finish 

    end 
end 

现在我的问题在这里,从设计的前瞻性,是它更好地创建Controller一个实例,并使用它与每个请求(像Idid与上面的代码一样),或为每个请求创建新的控制器实例(将@controller.register更改为Controller.new.register)?哪个更好用,为什么?

在此先感谢

回答

1

创建每个请求一个新的控制器的开销很可能没有那么大。

如果将状态存储在控制器(实例变量等)中并重新使用它,则可能会遇到并发问题,例如竞争条件或加载时的死锁。

如果你注意确保你的Controller对象不存储状态,你可以重用它。如果它为每个请求执行任何类型的状态存储,则需要确保共享资源属性同步。

我的2c - 为每个请求创建一个新的控制器,直到您确认您为每个请求创建一个新的控制器时性能降低。它更简单,更清洁,不易发生奇怪的错误。

+0

非常感谢,有道理。我认为压力测试可以给我一个表现。但我完全同意,每个请求的新控制器更简单更清洁 –

+0

我假设GC将在他们完成工作后清理新对象,我希望可以通过类似信号捕获的方式追踪该对象,以便检查对象的状态并当它被清理完毕后,如果你知道我应该怎么做,那会很棒。 –

+1

GC应在清除物体超出范围之后清理。我使用JRuby,所以我利用了JVM的GC,但我无法想象Ruby ruby​​会在周围留下陈旧的对象。 – mcfinnigan

相关问题