Rails の Rack::Timeout の機能強化
次の行をアプリケーションの Gemfile に追加します。
gem "slowpoke"
そして実行します:
rails generate slowpoke:install
これにより、カスタマイズ可能なpublic/503.html
が作成されます。
開発中にカスタム エラー ページを試すには、一時的にconfig/environments/development.rb
に追加します。
config . slowpoke . timeout = 1
config . consider_all_requests_local = false
そして、アクションの 1 つにsleep
コールを追加します。
sleep ( 2 )
カスタム エラー ページが表示されるはずです。
デフォルトのタイムアウトは 15 秒です。これはconfig/environments/production.rb
で次のように変更できます。
config . slowpoke . timeout = 5
動的タイムアウトの場合は、次を使用します。
config . slowpoke . timeout = lambda do | env |
request = Rack :: Request . new ( env )
request . path . start_with? ( "/admin" ) ? 15 : 5
end
以下を使用してタイムアウトをサブスクライブします。
ActiveSupport :: Notifications . subscribe "timeout.slowpoke" do | name , start , finish , id , payload |
# report timeout
end
詳細については、Rack::Timeout のドキュメントを参照してください。
Rack::Timeout はコード内のどの時点でも例外を発生させる可能性があり、アプリがクリーンでない状態になる可能性があります。リクエストのタイムアウトから回復する最も安全な方法は、新しいプロセスを生成することです。これはヤドンのデフォルトの動作です。
Puma のようなスレッドサーバーの場合、これは、いずれかのスレッドがタイムアウトになったときにすべてのスレッドを強制終了することを意味します。これはパフォーマンスに重大な影響を与える可能性があります。
この動作は次のようにカスタマイズできます。
Slowpoke . on_timeout do | env |
next if Rails . env . development? || Rails . env . test?
exception = env [ "action_dispatch.exception" ]
if exception && exception . backtrace . first . include? ( "/active_record/" )
Slowpoke . kill
end
end
注: 開発環境でenv["action_dispatch.exception"]
にアクセスするには、一時的にconfig/environments/development.rb
に追加します。
config . consider_all_requests_local = false
ステートメントのタイムアウトと接続のタイムアウトを設定することをお勧めします。 Postgres の場合、 config/database.yml
には次のようなものが含まれている必要があります。
production :
connect_timeout : 3 # sec
variables :
statement_timeout : 5s
変更ログを表示する
皆さんもこのプロジェクトの改善にご協力ください。以下にいくつかの方法があります。
開発を始めるには:
git clone https://github.com/ankane/slowpoke.git
cd slowpoke
bundle install
bundle exec rake test