2012-02-18 4 views
7

HerokuでUnicornを使用する場合。スケールアップすると、問題が発生します。なぜなら、新しくスケーリングされたWeb dynoには、まだアプリケーションをロードしているときに要求によってアクセスできるからです。ほとんどがタイムアウトエラーになります。私はHeroku + Unicornでアプリを正しくプリロードしていますか?

私はhttp://codelevy.com/2010/02/09/getting-started-with-unicorn.htmlhttps://github.com/blog/517-unicorn

2件の記事で読書のビットがpreload_app trueを使うことを提案しました。そしてafter_forkbefore_forkブロック。

Rails 3+では、まだbefore_blockのコードは必要ですか?私はどこかで読んだ。以前にこれを設定した経験があり、共有したい人は誰ですか?

私には他に何かがありますか?アプリをあらかじめ正しく読み込んでいますか?

# config/initializers/unicorn.rb 
# Read from: 
# http://michaelvanrooijen.com/articles/2011/06/01-more-concurrency-on-a-single-heroku-dyno-with-the-new-celadon-cedar-stack/ 
worker_processes 3 # amount of unicorn workers to spin up 
timeout 30   # restarts workers that hang for 90 seconds 

# Noted from http://codelevy.com/2010/02/09/getting-started-with-unicorn.html 
# and https://github.com/blog/517-unicorn 
preload_app true 

after_fork do |server, worker| 
    ActiveRecord::Base.establish_connection 
end 

before_fork do |server, worker| 
    ## 
    # When sent a USR2, Unicorn will suffix its pidfile with .oldbin and 
    # immediately start loading up a new version of itself (loaded with a new 
    # version of our app). When this new Unicorn is completely loaded 
    # it will begin spawning workers. The first worker spawned will check to 
    # see if an .oldbin pidfile exists. If so, this means we've just booted up 
    # a new Unicorn and need to tell the old one that it can now die. To do so 
    # we send it a QUIT. 
    # 
    # Using this method we get 0 downtime deploys. 

    old_pid = Rails.root + '/tmp/pids/unicorn.pid.oldbin' 
    if File.exists?(old_pid) && server.pid != old_pid 
    begin 
     Process.kill("QUIT", File.read(old_pid).to_i) 
    rescue Errno::ENOENT, Errno::ESRCH 
     # someone else did our job for us 
    end 
    end 
end 

答えて

2

ここに表示されている内容が必要です。 dynoでスケールアップすると、Herokuプラットフォームはそのスラッグをあなたの他のダイノス(つまり別のユニコーンマスター)から完全に分離された新しいdynoに展開します。

dynoがデプロイされて実行されている(効果的に起動されている)と、ルーティングメッシュはそのダイノーへのリクエストの送信を開始します。これは、RailsがUnicornなどのサーバで起動するときです。

ただし、その要求が到着すると、データを返すための30秒のウィンドウがあります。要求がルーティングメッシュでタイムアウトする(エラーH12)。

したがって、要約すると、問題はフォークすることではなく、アプリケーションが30秒以内に起動できないため、早期タイムアウトです。フォークとPIDファイルについて心配することは、Herokuプラットフォームで心配する必要があるものではありません。

+0

こんにちはNeil。解決策は、dyno(ユニコーンマスター)がアプリを完全に読み込むまでリクエストが入るのを防ぐために、アプリをプリロードすることです。私の心配は、 'before_fork'ブロックにコードが必要かどうかです。 –

+0

あなたのbefore_forkは何も達成できません。前にも述べたように、問題は、あなたのユニコーンが始まる前にHerokuルーティングメッシュがリクエストを送信するという事実にあります。アプリケーションをあらかじめロードしても、これは解決されません。 –

+0

これが当てはまる場合。ヘロクで新しいウェブダイノスを回転/拡大するときにタイムアウトエラーが発生するのを防ぐには? –

1

のみ部分的な答えが、私はこのユニコーン構成でこれらの厄介なスケーリングタイムアウトを削減することができました:

worker_processes 3 # amount of unicorn workers to spin up 
timeout 30   # restarts workers that hang for 30 seconds 
preload_app true 

# hack: traps the TERM signal, preventing unicorn from receiving it and performing its quick shutdown. 
# My signal handler then sends QUIT signal back to itself to trigger the unicorn graceful shutdown 
# http://stackoverflow.com/a/9996949/235297 
before_fork do |_server, _worker| 
    Signal.trap 'TERM' do 
    puts 'intercepting TERM and sending myself QUIT instead' 
    Process.kill 'QUIT', Process.pid 
    end 
end 

# Fix PostgreSQL SSL error 
# http://stackoverflow.com/a/8513432/235297 
after_fork do |server, worker| 
    defined?(ActiveRecord::Base) and 
    ActiveRecord::Base.establish_connection 
end 

はまた、私は(https://devcenter.heroku.com/articles/labs-preboot/を参照)heroku labs:enable prebootを使用しています。残念ながら、私はウェブダイノスをスケールアップするときにいくつかのタイムアウトを見ています。

ここHireFireサポートフォーラムでの議論だ、私は開始:http://hirefireapp.tenderapp.com/discussions/problems/205-scaling-up-and-down-too-quickly-provoking-503s

+0

同じアプローチに従うと助けにはならない。予圧をかけても、Unicornが "リスニング"を開始し、フォークされた労働者が "準備"している間に遅れがあるようです。私にとってこれは> 30秒ですから、*と*プレブートでもH12エラーが発生します。 –

1

preload_app trueを我々のアプリのために助けたので、あなたは、デプロイ/再起動中にタイムアウトの問題を見ている場合は、それに打撃を与えてください。私がそれが試してみる価値がないと思うようになったのを助けてくれないというコメントは、それが本当に私たちが必要としていた修正であることを実感しました。

私たちの状況は、遅い起動のRailsアプリでprebootを使用していました。一部の展開と再起動では、稼働時間の監視によってサイトがダウンしたと考えられるほど多くのタイムアウトが発生します。

preload_app falseとすると、Unicornはまずポートをバインドしてからアプリケーションをロードします。ポートをバインドすると、Herokuはトラフィックを送信し始めます。しかし、この遅いアプリがロードされるまでには時間がかかるため、トラフィックにタイムアウトが発生します。

これは、Unicornを起動した直後にサイトにアクセスしようとすると、「ポート上にサーバーがありません」というタイプのエラー(望ましい)または非常に遅いリクエスト望ましい)。

代わりにpreload_app trueを設定すると、Unicornがポートをバインドするまでに時間がかかりますが、一度実行してHerokuがトラフィックを送信すると、応答する準備が整います。

関連する問題