0

Railsには優れたフィルターのセット(before_validation、before_create、after_saveなど)とオブザーバーのサポートがありますが、フィルターまたはオブザーバーに依存することは計算コストが非常に高いという状況に直面しています。別の方法が必要です。

問題:Webサーバーのヒットを多数のページに記録しています。必要なのは、特定のページがX回以上表示されたときにアクション(たとえば、電子メールを送信する)を実行するトリガーです。ページとヒットの数が非常に多いため、フィルターまたはオブザーバーを使用すると、99%の時間、テストする条件が偽になるため、多くの無駄な時間が発生します。電子メールをすぐに送信する必要はありません(つまり、5〜10分の遅延が許容されます)。

代わりに私が検討しているのは、データベースを5分ごとにスイープし、どのページがX回以上ヒットしたかを確認し、その状態を新しいDBテーブルに記録してから、対応する電子メールを送信する、ある種のプロセスを実装することです。正確にはエレガントではありませんが、機能します。

他の誰かがより良いアイデアを持っていますか?

4

4 に答える 4

1

私はかつて、同じ要件を持つカスタム広告サーバーを作成したチームの一員でした。ドキュメントごとのヒット数を監視し、特定のしきい値に達したら何かを実行します。このサーバーは、大量のトラフィックを伴う既存の非常に大規模なサイトに電力を供給し、スケーラビリティが真の関心事でした。私の会社は、2人のDoubleclickコンサルタントを雇って彼らの頭脳を選びました。

彼らの意見は次のとおりです。情報を永続化する最も速い方法は、カスタムのApacheログディレクティブに書き込むことです。そこで、誰かがドキュメント(広告、ページ、すべて同じ)をヒットするたびに、リクエストを処理したサーバーがSQLステートメントをログに書き込むサイトを構築しました: "INSERT INTOインプレッション(タイムスタンプ、ページ、IPなど) )VALUES(x、'path / to / doc'、yなど); " --すべてがWebサーバーからのデータで動的に出力されます。5分ごとに、これらのファイルをWebサーバーから収集し、一度に1つずつマスターデータベースにダンプします。その後、暇なときに、そのデータを解析して、満足のいくことを何でも行うことができます。

正確な要件と展開の設定に応じて、同様のことを行うことができます。特定のしきい値を超えているかどうかを確認するための計算要件は、SQLを実行して値をインクリメントしたり行を挿入したりするよりも、おそらくさらに小さくなります(ここで推測します)。ヒット(特別な形式かどうかに関係なく)をログに記録することで、オーバーヘッドの両方のビットを取り除き、定期的に収集して解析し、データベースに入力して、必要な処理を行うことができます。

于 2009-05-23T15:53:14.530 に答える
1

レーキタスクはいいね!ただし、追加するバックグラウンド ジョブごとに、より多くのカスタム コードを記述することになります。Delayed Job プラグインをチェックしてくださいhttp://blog.leetsoft.com/2008/2/17/delayed-job-dj

DJ は、1 つの単純なデータベース テーブルに依存する非同期優先キューです。DJ の Web サイトによると、以下に示すDelayed::Job.enqueue()メソッドを使用してジョブを作成できます。

class NewsletterJob < Struct.new(:text, :emails)
  def perform
    emails.each { |e| NewsletterMailer.deliver_text_to_email(text, e) }
  end    
end  

Delayed::Job.enqueue( NewsletterJob.new("blah blah", Customers.find(:all).collect(&:email)) )
于 2009-05-22T22:52:09.260 に答える
0

ヒットモデルを保存するときに、ヒットの現在の合計を格納するページモデルの冗長列を更新します。これには、2つの追加クエリが必要になるため、各ヒットの処理に2倍の時間がかかる可能性がありますが、送信する必要があるかどうかを判断できます。簡単な場合はメール。

あなたの元の解決策も悪くはありません。

于 2009-05-22T22:07:05.730 に答える
0

stackoverflowコードが最初の行を強調表示するように、ここに何かを書く必要があります。

class ApplicationController < ActionController::Base
  before_filter :increment_fancy_counter

  private

  def increment_fancy_counter
    # somehow increment the counter here
  end
end

# lib/tasks/fancy_counter.rake
namespace :fancy_counter do
  task :process do
    # somehow process the counter here
  end
end

cronジョブを実行rake fancy_counter:processしますが、実行したい頻度は高くなります。

于 2009-05-22T22:09:07.317 に答える