Pumaでの設定
Rubyエージェントがアプリケーションをタイムアウトさせてしまい、サーバが起動できなくなることがあります。これは、サーバの設定によって防ぐことができます。
Pumaの設定は、CLIを使用してconfig/puma.rb
またはconfig.ru
ファイルで直接指定できます。
タイムアウトの設定
Contrastエージェントは、デフォルトの設定またはカスタム設定で動作するはずですが、最初のリクエスト処理でオーバーヘッドがかかります。 そのため、タイムアウトの設定時間を増やす必要がある場合があります。
重要
一部のオプションは、クラスタモードでのみ利用できます。 タイムアウトに利用できる全てのオプションは、puma/dsl.rbに記載されています。
persistent_timeout(seconds) - Pumaが持続的接続を閉じるまでのアイドル時間を定義します。seconds(秒数)には、整数を指定します。
first_data_timeout(seconds) - データが受信されなかった場合に、TCPソケットを開けている時間を定義します。seconds(秒数)には、整数を指定します。
*force_shutdown_after(val=:forever) * - スレッドをシャットダウンする際に、スレッドが停止するまで待機する時間を定義します。秒数も指定することができますが、
:forever
もしくは:immediately
を指定できます。:forever
- 値は-1に設定されます。:immediately
- 値は0 に設定されます。seconds
- タイムアウト値として、秒数を直接設定します。
注記
Pumaは即時モードであっても、シャットダウンの前に常に数秒間は待機します。
以下のオプションは、クラスタモードでのみ利用できます。
worker_timeout(seconds) - 指定したタイムアウト(秒数)内に、全てのワーカがマスタプロセスにチェックインしたかどうかを検証します。これはリクエストのタイムアウトではなく、プロセスの停止やハングアップを防ぐためのものです。この値を設定しても、時間の掛かるリクエストを防げるわけではありません。最小値は6秒、デフォルト値は60秒です。
worker_boot_timeout(seconds) - ワーカが起動する際のデフォルトのタイムアウトを変更します。指定されていない場合は、デフォルトはworker_timeoutの値になります。
worker_shutdown_timeout(seconds) - ワーカがシャットダウンする際のタイムアウトを設定します。
wait_for_less_busy_worker(val=0.005) - ソケットのリッスンを遅らせることにより、ビジーでないワーカにトラフィックをルーティングし、リクエストを最初に取得してもらうための待ち時間です。
注記
この設定はMRIでのみ機能します。他のインタプリタでは、この設定は無効です。
Pumaでは、最初に2つのデフォルトのタイムアウト値が設定されます。
DefaultWorkerTimeout = 60
DefaultWorkerShutdownTimeout = 30
全てのタイムアウトの設定を適用するには、Pumaをクラスタモードに設定してください。
フォーク
クラスタモードがPuma 5から導入され、Pumaはマスタプロセスから直接ではなく、ワーカ0からワーカをフォークできるようになりました。
preload_app
オプションと同様に、fork_worker
オプションを使用すると、アプリケーションは一度だけ初期化され、コピーオンライト(COW)メモリを削減できます。
このモードにはいくつかの利点があり、まず第一に、段階的な再起動(phased restart)と互換性があります。マスタプロセス自体は最初にアプリケーションをプリロードしませんので、このモードによって段階的な再起動が有効になります。段階的な再起動の一環としてワーカ0がリロードされると、最初にアプリケーションの新しいコピーが初期化されます。次に、他のワーカが、この新しいプリロード済みのアプリケーションが既にある新しいワーカから、フォークされてリロードされます。
ヒント
段階的な再起動は、Pumaクラスタ内の実行中のすべてのワーカを再起動します。これは、最初に古いワーカを終了させて、新しいワーカを起動し、新しいワーカが正常に起動するまで待ってから次のワーカに進みます。これを全てのワーカをに対して行います。 マスタプロセスは再起動されません。
この段階的な再起動は、ホットリスタートのように短時間で完了しつつ、クラスタのワーカを順に再起動することによりダウンタイムを最小限に抑えることができます。
もう一つの利点は、新しく追加されたrefork
コマンドによるコピーオンライト(COW)の改善です。ワーカ0からリフォーク(refork)することで、ワーカ0以外の全てのワーカをリロードします。
このコマンドは、起動時に完全に初期化できないような大規模や複雑なアプリケーションでのメモリ使用率を改善できる可能性があります。これは、リフォークされたワーカが、すでにリクエストを処理している実行中のワーカとコピーオンライト(COW)メモリを共有できるためです。
また、リフォークは、一定の数のリクエスト(デフォルトは1000)がワーカ0によって処理された場合にも、自動的に1度トリガーされます。自動リフォークされるまでのリクエスト数を設定するには、fork_worker
に正の整数値(例えば、fork_worker 1000)を指定するか、もしくは0を指定して無効にします。
制限事項:
クラスタモードはpreload_appと互換性がありません。
新しいワーカを正常にフォークするために、ワーカ0はサーバをシャットダウンし、リクエストの処理を停止します。これにより、プロセス間で共有されてオープン中のファイル記述子やその他のグローバルな共有状態がなくなり、新しくフォークされたワーカ間でコピーオンライト(COW)の効率が最大化されます。このため、段階的な再起動/リフォーク中にクラスタの総処理能力が一時的に減少する場合があります。
fork_workerおよびreforkコマンドについて説明しましたが、ほかにも以下のようなクラスタコマンド(forkワーカ)があります。
*workers(count) * - 実行するワーカプロセスの数。通常、使用可能なCPUコア数を設定します。 環境変数WEB_CONCURRENCYに値が設定されている場合は、それがデフォルトです。それ以外の場合は0です。
before_fork(&block) - マスタプロセスがワーカをフォークする前に実行(起動時に1回)するコード。プロセスが終了する前に、Pumaが関与しないバックグラウンド操作が終了するのを待機する必要がある場合に指定します。
on_worker_boot(&block) - アプリを起動する前にプロセスをセットアップするために、ワーカの起動時に実行するコード。
on_worker_shutdown(&block) - ワーカがシャットダウンする直前(HTTPリクエストの処理が完了した後)に実行するコード。
on_worker_fork(&block) - ワーカが起動する直前にマスタプロセスで実行するコード。ワーカのインデックスが引数として渡されます。
after_worker_fork(&block) - ワーカが起動された後にマスタプロセスで実行するコード。ワーカのインデックスが引数として渡されます。
on_refork(&block) - サーバがリクエストの受付けを一時的に停止した後、ワーカ0が他の全てのワーカをこのプロセスからリフォークする前に実行するコード(リフォークごとに1回呼び出されます)。コピーオンライト(COW)の効率を最大化するために追加のガベージコレクションのトリガとして使用できます。また、リモートサーバ(データベース、Redisなど)との接続を閉じるためにも使用できます。
out_of_band(&block) - ワーカがアイドル状態の時に不定期に実行されるコード。リクエスト処理が終わりワーカにビジー状態のスレッドが存在しなくなった直後に実行されます。このコードが終了するまで、ワーカは新しいリクエストを受付けません。これは、不定期のガベージコレクションを実行したり、レスポンスの後に実行する非同期タスクをスケジュールする場合に便利です。
fork_worker(after_request=1000) - この設定を有効にすると、ワーカはマスタプロセスからではなくワーカ0からフォークされます。このオプションは、アプリケーションがフォークする前にプリロードされるため"preload_app"に似ていますが、段階的な再起動と互換性があります。このオプションで
refork
コマンドも有効になります。nakayoshi_fork(enabled=true) - これは少し異なるオプションですが、ワーカをフォークする前にPumaが4回GC(ガベージコレクション)を実行します。起動とフォークの所要時間が長くなります。起動処理にかかる時間の詳細については、ログを参照してください。ほとんどのアプリケーションでは1秒以下になると考えられます。このフォーク方法は、笹田耕一氏とAaron Patterson氏の研究に基づいており、このオプションはプリロードを有効にしたクラスタモードのPumaのメモリ使用量を削減できる可能性があります。
注記
利用可能(Ruby 2.7以降)な場合、
GC.compact
も実行されます。MRI以外のRubyでは推奨されません。