適切なバックグラウンド ジョブ プロセッサの選択:遅延ジョブと Sidekiq の説明
ほとんどのアプリケーションでは、メーラー、定期的なクリーンアップ、またはユーザーの存在を必要としないその他の時間のかかる操作のためのバックグラウンド ジョブが必要です。
Rails の世界では、いくつかの gem がジョブ キューとバックグラウンド処理をサポートしています。Delayed Job と Sidekiq が最も人気のある 2 つです。
この投稿では、Delayed Job と Sidekiq の相互作用を含め、Delayed Job と Sidekiq について詳しく説明します。
行きましょう!
遅延ジョブの概要
遅延ジョブは Shopify から直接抽出され、テーブルを使用してすべてのバックグラウンド ジョブを維持します。非常に単純なパターンに従います。 perform に応答する任意の Ruby オブジェクト メソッドはジョブ テーブルのキューに入れることができます。
さらに、特別なジョブ オブジェクトを維持する必要がない場合 (ただし、これはテストのしやすさと長時間実行操作の明確な分離のために強く推奨されます)、.delay.method(params) を呼び出すこともできます。 任意の Ruby オブジェクト上で。メソッドはバックグラウンドで処理されます。
Delayed Job README は、一般的な使用パターンをすべて説明するのに優れています。
多くのチームは、シンプルで既存のデータベースを使用するため、遅延ジョブを選択します。他のリソースを費やしたり維持したりする必要はありません。
ただし、それでもデータベース テーブル内のスペースが占有されます。同時にキューに入れられるジョブが多すぎる場合は、すべてのジョブを収容するためにより多くのディスク容量が必要になる可能性があります。
Sidekiq の簡単な紹介
一方、Sidekiq は、すべてのジョブのメタデータを維持するためのデータ ストアとして Redis を使用します。これには、Delayed Jobs が使用する通常のデータベース システムよりもはるかに高速であるという明らかな利点が伴います。これに加えて、各 Sidekiq プロセスは複数のスレッドを生成して、ジョブをさらに高速に処理します。
Sidekiq の各バックグラウンド ジョブには、Sidekiq::Worker を含む特殊なクラスが必要です。 懸念し、perform に応答します ジョブをキューに入れるには、perform_async(arg1, arg2) を呼び出す必要があります。 ワーカーに引数を付けて実行します。
Sidekiq の「はじめに」ガイドでは、この使用パターンとその他の使用パターンについて詳しく説明しています。
アクティブ ジョブを遅延ジョブまたは Sidekiq とともに使用する
Rails は、トップレベルの宣言とジョブの処理のための成熟したジョブ フレームワークをすでに提供しています。Delayed Job と Sidekiq はどちらも、ActiveJob の統合 API を介したジョブの実行をサポートしています。ApplicationJob から継承するだけです。 perform_later を呼び出します ジョブ クラスでジョブを設定済みのキューイング バックエンドにエンキューします。
Active Job を使用してジョブを実行する利点は、アプリケーション コードがフレームワークに依存せず、Delayed Job から Sidekiq (またはその逆) への切り替えが非常に簡単になることです。 ActiveJob::TestHelper また、キューに入れられたジョブのテストも簡単になります。
ただし、Active Job によって提供される抽象化には、ジョブ データをストアにプッシュする前にラップする必要があるため、パフォーマンスのオーバーヘッドも伴います。Sidekiq によると、Redis にプッシュする場合、ActiveJob は約 2 ~ 20 倍遅くなり、処理オーバーヘッドは約 3 倍になります。
遅延ジョブ vs. Sidekiq
Delayed Jobs と Sidekiq の基本を理解したところで、それぞれの違いとそれぞれがもたらす影響について詳しく見ていきましょう。
特徴
基本的なアプリケーションの場合、Sidekiq と Delayed Job は両方とも、すぐに使える優れた機能セットを提供します。これには、ジョブの優先順位の割り当て、名前付きキュー、失敗時の自動再試行などがあります。
遅延ジョブでは、すぐに最大実行時間を設定する方法も提供されます (Sidekiq にはありません)。
一方、Sidekiq は、ジョブのメタデータを更新したり、ジョブのキューをスキップしたり、ジョブを実行したりするためのミドルウェアのサポートを提供します。Sidekiq はより多くのコールバックをサポートしますが、一部のフックは遅延ジョブ アプリで使用できます。コールバックの代わりに、遅延ジョブとアクティブ ジョブ (つまり、before_enqueue) を使用できます。 と around_perform Rails に組み込まれたコールバック)。
Web UI は、Sidekiq ですぐに使えるもう 1 つの機能です。これにより、ジョブに関する履歴統計と、ワーカー、現在キューに入れられているジョブ、および無効なジョブに関する情報が提供されます。コンソールを介さずに、ジョブの削除や実行などの操作をすぐに実行できます。
遅延ジョブには組み込みの Web UI はありませんが、delayed_job_web Sidekiq と同様の機能を備えた基本的な Web UI にアクセスできます。
Sidekiq がパフォーマンスで勝利
パフォーマンスの面では、Sidekiq は Delayed Job をかなりの説得力で上回っています。Sidekiq のオープンソース ベンチマークによると、Sidekiq は Delayed Job よりも約 30 倍高速です。これには主に 2 つの理由があります。
<オル>これらはすべて紙の上では素晴らしく見えますが、大規模な作業 (1 分あたり 10,000 ジョブなど) を行わない限り、違いはそれほど重要ではありません。正確な数は、ジョブの平均実行時間にも依存します。実行時間が長いほど、遅延ジョブのパフォーマンスのオーバーヘッドは重要ではなくなります。
遅延ジョブのパフォーマンスが心配な場合は、いくつかのパフォーマンスの最適化を行うことができます。使用する正確なインデックスは、ジョブ システムの統計によって異なります。たとえば、複数のキューを使用していて、1 つのキューだけがジョブの主要な部分を取得する場合は、キュー列 (add_index :delayed_jobs, :queue) に単純なインデックスを作成します。 ) パフォーマンスを大幅に向上させることができます。
AppSignal では、Sidekiq マジック ダッシュボードが自動的に生成され、キューの長さ、キューのレイテンシー、ジョブの継続時間、ジョブのステータス、メモリ使用量などを監視できます。

展開
Delayed Job と Sidekiq はどちらも、ワーカーに対して同様のデプロイ戦略を持っています。 Heroku を使用すると、Procfile 内にエントリを追加するだけです。 ジョブ プロセッサを起動し、ワーカーを実行します。
Sidekiq の場合:
遅延ジョブの場合:
メモリ
ここからが少し面白くなります。 Sidekiq には、実行するスレッドの数を制御する同時実行オプションがあります。Sidekiq と遅延ジョブのベンチマークのほとんどでは、Sidekiq の最大 25 スレッドという非常に高い同時実行性が言及されており、これが超高速パフォーマンスに貢献しています。
しかし、実際の設定では、スレッドをより控えめなものに制限する必要があります。実際の数は、アプリケーションの重さと、実行するジョブの種類によって異なります。実際に私が見たことは、ワーカーを 512MB メモリ (standard-1x に相当) で実行した場合です。 Heroku では)、スレッド数は 25 ではなく 2 ~ 5 の間になります。
Sidekiq の作成者である Mike Perham による「Taming Rails Memory bloat」では、メモリの問題についてさらに詳しく説明されており、一読の価値があります。詳細な説明には立ち入りませんが、彼は MALLOC_ARENA_MAX=2 を設定することを推奨しています。 Sidekiq を実行するすべてのワーカーに適用されます。
jemalloc を使用する 通常の malloc の代わりに も役立ちます。これを行う正確な方法は使用するプラットフォームによって異なりますが、Heraku では非常に簡単です。 heroku-buildpack-jemalloc を最初のビルドパックとして設定するだけです (heroku/ruby より前) ビルドパック)。
遅延したジョブはより単純なリソースを使用する
説明したように、遅延ジョブは既存のデータベース インスタンスで実行されます。次の値を増やす必要がある場合があります。
- 利用可能なメモリ
- ディスク容量
- 最大接続数
ジョブの負荷または実行するワーカーの数に応じて異なります。ただし、必要なリソースはジョブ プロセッサだけです。
一方、Sidekiq はジョブを処理するために Redis インスタンスを必要とします。Redis をキャッシュ ストアとしても使用する場合は、Sidekiq ジョブ用に「永続ストア」として構成された別のインスタンスを使用することをお勧めします。
Redis はすべてがメモリに収まるときに最適に機能するため、ジョブが多すぎる場合 (たとえば、アプリの問題により Sidekiq がしばらくジョブの処理を停止した場合)、すべてをクリアするのにダウンタイムがかかる可能性があります。これは、アプリと同じサーバー上に Redis がある場合に特に問題になります。ジョブはメモリを求めて競合し始め、スワップが発生し、最終的にはアプリのパフォーマンスが破壊されます。
Redis について注意すべき重要な点の 1 つは、maxmemory-policy noeviction で構成する必要があることです。 Sidekiq のデータがサイレント ドロップされるのを避けるためです。そうしないと、実行する必要があるジョブが跡形もなく失われることになります。
補足:Sidekiq の有料アップグレード
追加の機能が必要な場合は、Sidekiq に Pro が付属しています。 および Enterprise バージョン。
Pro への最も注目すべき追加点は Batch Jobs です。 並列実行、監視、グループとしての対話が可能で、すべてのジョブが完了するとコールバックを呼び出します。また、Pro では信頼性機能も向上しており、ネットワークに問題がある場合でも、ジョブが通知なくドロップされないことが保証されます。
Enterprise バージョンにはさらに多くの機能が付属しています。通常の Sidekiq インストールでは解決できない問題を探している場合は、有料の Sidekiq 機能を調べてください。
実際には、Sidekiq の無料バージョンは依然として問題なく機能します。しかし、別のソリューションに切り替える代わりに、必要に応じてアップグレードできる有料オプションがあることを知っておくと良いでしょう。
コミュニティと開発状況:Sidekiq が優位性を持っています
Sidekiq と Delayed Job の背後には巨大なコミュニティがあります。ただし、StackOverflow や公式ドキュメントで質問に対する簡単な答えを見つけるのは必ずしも簡単ではありません。
開発面では、Delayed Job の状況はあまり明るいとは言えません。2021 年 12 月と 2022 年 1 月に Delayed Job でいくつかの小規模な作業が行われましたが、今後大きな開発は行われていないようです。メンテナンス専用モードになっているようで、Github には未解決の問題が多数あります。
対照的に、Sidekiq はまだ積極的に開発中であり、作成者はフルタイムで取り組んでいます。未解決の問題はほとんどなく、定期的に対処されています。
まとめ:Sidekiq または遅延ジョブ?それはあなたのニーズ次第です
この投稿では、Rails アプリケーション用の 2 つの主要なジョブ処理システム、Sidekiq と Delayed Job について説明し、それぞれの長所と短所をいくつか取り上げました。
それぞれに異なる使用例があります。すべては予算と事業の規模によって異なります。
パフォーマンスと長期的な保守性が重要な場合は、Sidekiq を使用するのは間違いありません。一方、ランニングコストが懸念される場合は、Delayed Job が役立ちます。
Delayed Job を選択するか Sidekiq を選択するかに関係なく、プロジェクトの成功とコーディングの成功を祈ってください。
👋 この記事が気に入ったら、Ruby パフォーマンス監視チェックリストの他の Ruby (on Rails) パフォーマンス記事をご覧ください。
追記Ruby Magic の投稿を報道後すぐに読みたい場合は、Ruby Magic ニュースレターを購読して、投稿を 1 つも見逃さないようにしてください。
-
クライアント側キャッシュによる Rails のパフォーマンスの向上:マスター条件付き GET リクエスト
ロシアン ドール キャッシュ以外にも、Rails アプリのパフォーマンスを高速化するテクニックは他にもあります。今回は、Rails の組み込み条件付き GET サポートについて見ていきます。これにより、レンダリングされたページをユーザーのブラウザ キャッシュに保存できるようになります。 👋 キャッシュ以外のパフォーマンスについて詳しく読みたい場合は、Ruby (on Rails) のパフォーマンスについてさらに詳しく書いています。Ruby のパフォーマンス監視チェックリストを確認してください。 Etag ヘッダーと Last-Modified ヘッダー ブラウザが Rails アプリ内の
-
Ruby転置法を使用して行を列に変換する
今日は、Ruby転置法を使用してRubyでグリッドを処理する方法を学習します。 多次元配列の形をした完璧なグリッド、たとえば3×3の正方形があると想像してみてください。 そして、行を取得して列に変換する 。 なぜあなたはそれをしたいのですか? 1つの用途は、古典的なゲームであるtic-tac-toeです。 ボードをグリッドとして保存します。次に、勝利の動きを見つけるには、行を確認する必要があります 、列 &対角線 。 問題は、グリッドを配列として格納している場合、行に直接アクセスすることしかできないことです。 コラムズザハードウェイ 「直接アクセス」とは、配列を(eachで)調べ