我有一个非常大的rails应用程序,我已经阅读了关于如何减少启动时间的每个帖子,每个都建议减少模型或控制器或宝石,但所有这些都被使用。
我面临的问题是heroku推送R10错误代码,因为我的应用需要超过60秒才能加载。
我一直在尝试一件事,几乎成功了。我试图运行Bundler.require和Application.inialize!在线程中(后一个线程等待第一个完成)。这样做的好处就是瘦服务器几乎立即启动。
问题是,当有人用请求命中应用程序时,初始化过程仍然不完整。知道如何实现这个目标吗?
答案 0 :(得分:0)
您可以通过扩展initialize!
中的config/application.rb
方法来控制初始化过程。
从github项目中查看此sample application.rb
file。您应该能够在initialize!
范围内扩展class Application < Rails::Application
方法。
您可以从第2.3节railties / lib / rails / application.rb中的Rails Initialization docs获取基本方法。因此,如果您扩展方法并将它们保留为默认实现方式,那么这就是您所拥有的。
class Application < Rails::Application
def initialize!(group=:default) #:nodoc:
raise "Application has been already initialized." if @initialized
run_initializers(group, self)
@initialized = true
self
end
def run_initializers(group=:default, *args)
return if instance_variable_defined?(:@ran)
initializers.tsort_each do |initializer|
initializer.run(*args) if initializer.belongs_to?(group)
end
@ran = true
end
end
此时,您可以添加打印报表并确定您遇到的问题。例如,您的@initialized
变量是否永远不会设置为true
?如果是这样,为什么?也许你被困在run_intializers
里面。如果是这种情况,那么你会陷入哪个初始化器?
答案 1 :(得分:-1)
我意识到我想做的事情是不可能的。所以我结束了这个主题。
我在做什么: 在我的environment.rb中,
def init_bundler
# If you want your assets lazily compiled in production, use this line
s = Time.now
_rails_groups = (ENV["RAILS_GROUPS"]||"").split(",")
if _rails_groups.length == 1 and _rails_groups.first.to_s == "assets"
Bundler.require(:assets) #load ONLY assets ..
elsif _rails_groups.length == 1 and _rails_groups.first.to_s == "clock"
Bundler.require(:clock) #load ONLY assets ..
else
Bundler.require(:default, *_rails_groups, Rails.env.to_s)
end
puts "bundler required in #{Time.now - s}s"
end
puts "starting t1"
$_t1 = Thread.new{ init_bundler }
在我的环境中.rb:
def init_app
# Initialize the rails application
puts "initialize started"
s = Time.now
Hedgepo::Application.initialize!
puts "initialize done in #{Time.now - s}s"
end
puts "starting t2"
$_t2 = Thread.new do
loop do
if defined?($_t1) and !$_t1.status
init_app
break
else
puts "waiting for bundler"
end
sleep(1)
end
end
我正在使用的中间件高于其他人:
class MyInit
def initialize(app)
@app = app
end
def call(env)
loop do
if defined?($_t2) and !$_t2.status
break
else
puts "waiting for app init to finish...."
end
sleep(1)
end
@app.call(env)
end
end
但问题是Rack :: Server在命中时分配了一个'app'变量和.start!s服务器。所以无论我做什么,我都无法更改在填充此@app变量之前初始化的应用程序。