スケジュールに従って、またはいくつかのパラメーターを使用してバックグラウンド プロセスとして実行する必要があるコードがよくあります。共通の要素は、それらがディスパッチ プロセスの外で実行されることですが、Rails 環境 (および場合によっては渡されたパラメーター) へのアクセスが必要です。
これを整理する良い方法とその理由は何ですか? 特定のプラグインや gem を使用したい場合は、なぜ便利だと思うのかを説明してください。使用しているプラグインだけを挙げてはいけません。
スケジュールに従って、またはいくつかのパラメーターを使用してバックグラウンド プロセスとして実行する必要があるコードがよくあります。共通の要素は、それらがディスパッチ プロセスの外で実行されることですが、Rails 環境 (および場合によっては渡されたパラメーター) へのアクセスが必要です。
これを整理する良い方法とその理由は何ですか? 特定のプラグインや gem を使用したい場合は、なぜ便利だと思うのかを説明してください。使用しているプラグインだけを挙げてはいけません。
非同期ジョブを実行する目的でデータベースに保持されるような宝石は本当に好きではありませんdelayed_job
。background_job
それは私には汚れているようです。一時的なものはデータベースに属しません。
大規模なスケーラビリティが必要ない場合でも、非同期タスクを処理するためのメッセージ キューの大ファンです。私の見方では、メッセージ キューは複雑なシステムにとって理想的な「共通語」です。メッセージ キューを使用すると、ほとんどの場合、構築するものに関係するテクノロジや言語に制限がありません。並行性の低いメッセージ キューを使用する利点は、おそらく、統合が常に大きな苦痛を伴う「エンタープライズ」環境で最も顕著になります。さらに、メッセージ キューは、非同期ワークフローに複数のステップが含まれる場合に最適です。RabbitMQ は私の個人的なお気に入りです。
たとえば、検索エンジンを構築しているシナリオを考えてみましょう。ユーザーは、索引付けする URI を送信できます。明らかに、要求されたページを取得してインデックス付けする必要はありません。したがって、メッセージ キューを中心に構築します。フォーム送信ターゲットは URI を取得し、それをメッセージ キューにスローしてインデックスを作成します。次に利用可能なスパイダー プロセスは、キューから URI を取り出し、ページを取得し、すべてのリンクを見つけ、不明な場合はそれぞれをキューにプッシュし、コンテンツをキャッシュします。最後に、新しいメッセージが 2 番目のキューにプッシュされ、インデクサー プロセスがキャッシュされたコンテンツを処理します。インデクサー プロセスは、そのメッセージをキューからポップし、キャッシュされたコンテンツにインデックスを付けます。もちろん、単純化しすぎています — 検索エンジンは大変な作業ですが、そのアイデアは理解できます。
実際のデーモンに関しては、明らかに、私は自分のライブラリ (ChainGang) に偏っていますが、それは実際には Kernel.fork() の単なるラッパーであり、セットアップとティアダウン コードを処理するのに便利な場所を提供します。また、まだ完全には完了していません。デーモン部分は、実際にはメッセージ キューほど重要ではありません。
Rails 環境に関しては、これはおそらく読者の演習として残しておくのが最善でしょう。なぜなら、実行時間の長いプロセスではメモリ使用量が重要な要素になるからです。必要のないものはロードしたくありません。ちなみに、これは DataMapper が ActiveRecord の尻をしっかり蹴っている 1 つの領域です。環境の初期化は十分に文書化されており、関与する依存関係がはるかに少なくなるため、キット全体とキャブドルが大幅に現実的になります。
cron+rake について私が気に入らないことの 1 つは、rake が標準出力に出力することが事実上保証されていることと、cron ジョブが出力を生成する場合、cron が過度にチャットする傾向があることです。すべての cron タスクを適切な名前のディレクトリに置き、それらをラップする rake タスクを作成して、手動で簡単に実行できるようにするのが好きです。rake がこれを行うのは残念です。なぜなら、私は依存関係を利用するオプションがあることを本当に望んでいるからです。いずれにせよ、cron 経由でスクリプトを実行するのではなく、スクリプトに直接 cron を向けるだけです。
私は現在、非同期プロセスに大きく依存する Web アプリケーションを作成している最中です。Rails を使用しないことに決めて、本当に本当に良かったと言わざるを得ません。
私にとっては、余分なインフラストラクチャを維持したくないことが重要な優先事項であるため、Rails の外部で実行されるデータベース バックアップ キューを使用しました。
私の場合は、delayed_jobbackground_job
を使用しました。では、ワーカーは cron 経由で実行され続けていたため、デーモン管理はありませんでした。では、私は Heroku を使用していて、その心配を彼らに任せています。background_job
delayed_job
delayed_job を使用すると、バックグラウンド ワーカーの実行に必要な数の引数を渡すことができます。
Delayed::Job.enqueue(MyJob.new(param[:one], param[:two], param[:three])
script/runner
cron を使用する以外に、スケジュールに従って実行するための良い解決策が見つかりませんでした(script/runner
コードをテストする方が簡単だと思うので、Rake タスクよりも使用する方が好きです)。
特定の Rails リクエストへのアクセスを必要とするバックグラウンド プロセスを定期的にスケジュールする必要はなかったので、それほど問題にはなりませんでした。
より多くの機能を備えた他のよりクールなシステムがあることは知っていますが、これは私にとっては問題なく機能し、管理するために多くの新しいサービスを設定する必要がなくなりました.
リクエストを受信し、Web サービスを使用して複数の外部システムを呼び出す必要があるシステムがあります。これらのリクエストの中には、ユーザーが予想されるよりも長くかかるものもあり、これらのリクエストを処理するためにエンタープライズ キューイング システム (activemq) を使用しています。
これを行うためにActiveMessagingプラグインを使用しています。これにより、リクエストをマーシャリングし、リクエスト データにアクセスして非同期処理のキューに入れることができますが、レスポンスを待ちたい場合は、ポーリング サービスを作成する必要があります。
Starling と Worklingで Ryan Bates の railscast を見たことがあります。
定期的にスケジュールされたタスクには、rake タスクのみを使用します。シンプルで、テストしやすく、理解しやすく、Rails 環境とうまく統合できます。次に、必要な間隔で cron ジョブを使用してこれらの rake タスクを実行するだけです (私はcron に少し慣れていないので、これらのジョブを管理するためにいつでも使用します)。