Sidekiq MemoryKiller

GitLab Railsアプリケーションのコードはメモリリークに悩まされています。 ウェブリクエストの場合、この問題はpuma-worker-killer 。メモリ制限を超えるとPumaワーカープロセスを再起動します。 Sidekiq MemoryKillerは、GitLabがバックグラウンドジョブを処理するために使っているSidekiqプロセスに同じアプローチを適用します。

GitLab 13.0以降、すべてのGitLabインストールでデフォルトで有効になっているpuma-worker-killerとは異なり、Sidekiq MemoryKillerはOmnibus_パッケージでのみ_デフォルトで有効になっています。 その理由は、MemoryKillerはメモリによるシャットダウン後にSidekiqを再起動するためにrunitに依存しており、ソースからインストールしたGitLabがすべてrunitや同等のものを使っているとは限らないからです。

デフォルト設定では、MemoryKillerがSidekiqを再起動する頻度は15分に1回以下となり、再起動によりバックグラウンドジョブの受信に約1分の遅延が発生します。

バックグラウンドジョブの中には、長時間実行される外部プロセスに依存しているものがあります。 Sidekiqの再起動時にこれらのプロセスがきれいに終了するように、各Sidekiqプロセスをプロセスグループリーダーとして実行する必要があります(例:chpst -Pを使用)。Omnibusまたはrunit がインストールされたbin/background_jobs スクリプトを使用している場合、この処理が行われます。

MemoryKillerの設定

MemoryKillerは環境変数を使って制御します。

  • SIDEKIQ_DAEMON_MEMORY_KILLERデフォルトは0です。 1に設定すると、MemoryKillerは_デーモン・_モードで動作します。 1に設定しないと、MemoryKillerは_レガシー・モードで_動作します。

    レガシー・モードでは、MemoryKillerは各ジョブの後にSidekiqプロセスRSSをチェックします。

    _デーモン_モードでは、MemoryKillerは3秒ごとにSidekiqプロセスのRSSをチェックします(SIDEKIQ_MEMORY_KILLER_CHECK_INTERVALで定義)。

  • SIDEKIQ_MEMORY_KILLER_MAX_RSS (KB)この変数が設定され、その値が0より大きい場合、MemoryKillerは有効になります。 そうでない場合、MemoryKillerは無効になります。

    SIDEKIQ_MEMORY_KILLER_MAX_RSS は、Sidekiqプロセスが許可するRSSを定義します。

    レガシーモードでは、Sidekiqプロセスが許容RSSを超えた場合、不可逆的な遅延猶予再起動がトリガーされます。 Sidekiqの再起動は、SIDEKIQ_MEMORY_KILLER_GRACE_TIME 秒後に行われます。

    _デーモン_モードでは、Sidekiqプロセスが許容RSSを超える時間がSIDEKIQ_MEMORY_KILLER_GRACE_TIME を超えると、グレースフル・リスタートがトリガーされます。SidekiqプロセスがSIDEKIQ_MEMORY_KILLER_GRACE_TIME以内に許容RSSを下回ると、再起動は中断されます。

    Omnibusパッケージのデフォルト値は、Omnibus GitLabリポジトリに設定されています。

  • SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS (KB)SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS:SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS デーモン SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSSモードでSIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS 使用されます。 SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSSSidekiSIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS qプロセスのRSS(キロバイトで表示) SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSSが、 をSIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS 超えると SIDEKIQ_MEMORY_KILLER_HARD_LIMIT_RSS、Sidekiqの即時グレースフルリスタートがトリガーされます。

  • SIDEKIQ_MEMORY_KILLER_CHECK_INTERVALデーモン・モードでは、プロセスのRSSをチェックする頻度を定義します。

  • SIDEKIQ_MEMORY_KILLER_GRACE_TIMEデフォルトは900秒(15分)。この変数の使い方は、SIDEKIQ_MEMORY_KILLER_MAX_RSSの一部として説明されています。

  • SIDEKIQ_MEMORY_KILLER_SHUTDOWN_WAITデフォルトは30秒です。 これは、すべてのSidekiqジョブが終了するまでに許容される最大時間を定義します。 この時間内は新しいジョブは受け付けられず、すべてのジョブが終了すると同時にプロセスは終了します。

    その間にジョブが終了しない場合、MemoryKillerはSidekiqプロセスにSIGTERM 、現在実行中のすべてのジョブを中断します。

    プロセスのハードシャットダウン/再起動がSidekiqによって実行されない場合、SidekiqプロセスはSidekiq.options[:timeout] * 2 秒後に強制終了されます。外部監視メカニズム(runitなど)は、その後Sidekiqを再起動する必要があります。