每次请求时,都会启动一个新的Sinatra实例吗?

9
当有新的http请求进来时,是否会启动一个新的sinatra实例,例如是否需要初始化sinatra,还是只调用先前实例(对应的get/post方法/路由)?
谢谢提供文档链接,我找不到任何相关资料。
同时,这种行为是否取决于部署类型 - WEBrick/Passenger等也很有趣。

我看到了很多关于如何强制Sinatra/Rack重新加载源文件和应用程序的讨论,所以我的猜测是它们默认情况下没有被重新加载,我的理解正确吗? - Oleg Mikheev
是否知道这种行为是否取决于部署类型也是非常有趣的——WEBrick和Passenger在这方面的行为是否相同? - Oleg Mikheev
@Oleg:重新加载Ruby源文件和创建新实例是不同的概念。前者可以通过requireload来完成,而后者则是TheClass.new - miaout17
@Oleg:我赞同miaout17的观点,这个问题完全不涉及重新加载源文件。 - user562529
4个回答

13

每个请求都会创建一个新的类。然而,这不是由Rack完成的,这是Sinatra的一个特性。如果您想深入了解细节:实例实际上并不是使用Sinatra::Application.new创建的,而是使用Sinatra::Application.prototype.dup创建的,请参阅Sinatra::Base#call中的代码。


实际上将这些信息添加到Sinatra文档站点中是有意义的。 - Oleg Mikheev
5
确实有记录:http://www.sinatrarb.com/intro#Request/Instance%20Scope - Konstantin Haase
2
那么把链接放到你的答案中就有意义了 :) - Oleg Mikheev
Konstantin,你真的太有帮助了!但是我除了放弃Sinatra之外,没有任何办法解决这个问题。如果每次都打开一个新的数据库连接,我宁愿转向另一个平台。也许我最终只能带着失败的尾巴回到Rails。 - mjnissim
哇,这让我现在感到非常轻松。谢谢! - nex
显示剩余2条评论

2
您应该始终假设在请求之间整个应用程序可能会在您下面重新启动。如果您运行16个应用程序副本,则用户“简”的'/'请求可能会出现在副本#2上,然后当她访问'/signup'时,请求将命中#12(可能为此事件而引导)应用程序。因此,Sinatra正在做什么并不重要(尽管它看起来他们做了类似的事情),因为您的应用程序可能随时出现在任何地方,今天启动,昨天或1毫秒前。
如果您计划增长-或在Heroku等平台上部署-则您的应用程序需要使用'shotgun'正常运行-每个请求都会重新启动一切。我猜,如果您的应用程序执行的操作与提供Web页面有很大不同,并且几乎从不崩溃或重新启动,则可以使用“NO”。
所以我的答案是'YES'(但不总是,甚至有时通常也不是)。
尽管如此,了解事物如何工作很方便,这样您就可以只针对每个应用程序加载设置一次复杂的计算资产缓存方案-这是性能优化。例如,如果每次使用url /calculate_pi?decimals = 2000调用您的应用程序始终会得到相同的2000位数字,则可以在每个实例上缓存该数字。

谢谢你提供实用的答案。我肯定不会依赖于始终拥有相同的实例。知道事情是如何工作的很方便,这就是我问这个问题的原因。“所以我的答案是'是'(但并不总是,甚至有时通常也不是)。”这对于理解“请求周期”如何工作非常有帮助。抱歉我的问题表述得不好。 - user562529

0
一个快速的测试表明,无论请求是什么(至少默认情况下),相同的实例正在运行。
require 'sinatra'

flag = false

get '/stuff' do
  puts "flag is #{flag ? 'set' : 'unset'}"
  flag = true
end

当运行此代码并接收到两个请求时,服务器将提示“flag未设置”,然后是“flag未设置”。
编辑:
这表明文件没有重新加载。通过使用puts self.object_id, self.class(如pguardiario建议的那样),我们实际上可以看到每个请求都会创建一个新的Sinatra::Application实例。

1
这不是说明它是一个不同的实例吗?也许更好的测试是:puts self.object_id - pguardiario
好的,这表明文件没有像@Oleg所说重新加载,你是对的:通过self.object_id,我们可以看到每个请求都有一个不同的Sinatra :: Application实例。我现在会立即编辑我的答案。 - tomferon
再次运行ruby testfile2.rb时,第一次调用标志未设置,所有后续调用都设置了标志。使用shotgun始终未设置标志。因此,在Web服务器中依赖这种行为是个坏消息。 - Tom Andersen
因此,每次调用时都会有一个新的Sinatra:Application实例,但是设置的“flag”变量在使用“正常”服务器时会被保留。 - Tom Andersen
当将标志设置为@变量 - 类变量时,情况会发生变化。在这种情况下,每次调用时都会得到未设置的@flag,这是有道理的。 - Tom Andersen

0

运行这个,你会知道一切,但这并不意味着 Rack 的机制像 Sinatra 一样运行。(实际上,Rack 会为每个请求创建一个新的实例)

require 'sinatra'

configure do
    set :number, 0
end

number = 0

get '/test1' do
    var = "The number is #{number}"
    number = number + 1
    var
end

get '/test2' do
    var = "The number is #{settings.number}"
    set :number, settings.number + 1
    var
end

将此文件作为“ruby test file.rb”运行,并在浏览器中点击test1会显示“数字为0”,然后是“数字为1”,最后是“数字为2” - 然后切换到点击test2,它又从0开始上升。 - Tom Andersen
使用“shotgun”运行此文件始终会导致“数字为0”,无论您做什么。 - Tom Andersen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接