質問

アイテムが検索またはリストページで表示される回数のログと計算に興味があります。 1日に50kのユニークな訪問者がいるため、1日あたり3〜400万人の「インプレッション」を生み出すことができると予想していますが、これはひどく大量ではありませんが、私たちはうまく建築したいと思います。

このデータをリアルタイムで読む必要はありませんが、ビジネス分析ツールと同様に、毎日の合計を生成し、トレンドなどを分析できるようにしたいと考えています。

ページがレンダリングされた後、AJAXの投稿でこれを行うことを計画しています。これにより、これらの結果がキャッシュされていても結果をカウントできます。これを1ページごとに1つの投稿で行うことができ、ページ上のIDとその位置のコンマ区切りリストを送信できます。

これについてのデザインパターン/GEM/ブログの投稿があることを願っています。また、ログのログや読み物の読み物の経験はあまりありません。

私の現在の戦略 - ログファイルにイベントを書く何かを作成し、1日の終わりに結果を集計し、結果をMySQLに戻すためのバックグラウンドジョブを作成します。

役に立ちましたか?

解決

アイテムをリストするのに必要なアクションがないことに応じて、コントローラーでそれを行い、往復することができるかもしれません。 afth_filterでそれを行うことができ、追加を控えめにすることができます。

これは、ログを記載するアイテムをリストするすべてのアクションにパラメーターが必要な場合にのみ機能します。これは、Page Cachingがパラメーターを使用してGETリクエストを無視するためです。

検索アクションに関する検索データのみを記録するだけであると仮定します。

class ItemsController < ApplicationController
  after_filter :log_searches, :only => :search

  def log_searches
    @items.each do |item|
      # write to log here
    end
  end

  ...
  # rest of controller remains unchanged
  ...
end

それ以外の場合は、Ajaxとオンロードリモート機能で順調に進んでいます。

処理に関しては、Cronジョブが実行するレーキタスクを使用して統計を収集し、場合によっては人気評価のためにアイテムを更新できます。

いずれにせよ、あなたは ルビーロギングクラス. 。 Cronの仕事やレーキのタスクについて学ぶことも傷つくことはありません。

他のヒント

わかりました、私はあなたのために3つのアプローチがあります:

1)キュー

Ajaxハンドラーで、可能な限り単純な方法(ラックミドルウェアまたはRails Metalを使用)を書き、クエリパラメーションをキューに押し込みます。次に、キューを投票してメッセージを収集します。

ラックからプッシュされるキューミドルウェアは目がくらむほど速いです。これは、同様のデータを記録するために非常に高い交通サイトで使用します。

ラックのサンプルミドルウェアは以下にあります(アプリから抽出され、2ms未満でリクエストを処理できます。

class TrackingMiddleware
  CACHE_BUSTER = {"Cache-Control" => "no-cache, no-store, max-age=0, must-revalidate", "Pragma" => "no-cache", "Expires" => "Fri, 29 Aug 1997 02:14:00 EST"}

  IMAGE_RESPONSE_HEADERS = CACHE_BUSTER.merge("Content-Type" => "image/gif").freeze
  IMAGE_RESPONSE_BODY = [File.open(Rails.root + "public/images/tracker.gif").read].freeze

  def initialize(app)
    @app = app
  end

  def call(env)
    if env["PATH_INFO"] =~ %r{^/track.gif}
      request = Rack::Request.new(env)
      YOUR_QUEUE.push([Time.now, request.GET.symbolize_keys])
      [200, IMAGE_RESPONSE_BODY, IMAGE_RESPONSE_HEADERS]
    else
      @app.call(env)
    end
  end
end

キューにはお勧めします スターリング, 、私はそれで楽しい時間を過ごしました。

解析の終わりに、私は使用します スーパーポラーツールキット, 、しかし、私はそれを書いたと思います。

2)ログ

Query Paramsを静的ファイル(/1x1.gif?foo=1&bar=2&baz=3)にすべてのパラメーションを渡します。これはRailsスタックに衝突することはなく、目がくらむほど速くなります。

データが必要な場合は、ログファイルを解析するだけです!

これは、最高のスケーリングホームブリューアプローチです。

3)Googleアナリティクス

Googleがあなたのためにそれを行うのに、なぜ負荷を処理するのですか? Google Analyticsがどれほど優れているかに驚くでしょう。家に帰る前に、チェックしてください!

Googleはあなたよりも速くサーバーを購入するため、これは無限にスケーリングされます。


私はこれについて何年もの間怒ることができましたが、私は今行かなければなりません。お役に立てれば!

これは私が最終的にしたことです - 今のところ私たちの使用には十分であり、いくつかの簡単なベンチマークで、私はそれについて大丈夫だと感じています。顧客に結果を公開する前に、生産がどのように行われているかを確認します。

コンポーネント:

class EventsController < ApplicationController
  def create
    logger = Logger.new("#{RAILS_ROOT}/log/impressions/#{Date.today}.log")
    logger.info "#{DateTime.now.strftime} #{params[:ids]}" unless params[:ids].blank?
    render :nothing => true
  end
end

これは、サイトレイアウトのAJAXコールから呼び出されます...

<% javascript_tag do %>
  var list = '';
  $$('div.item').each(function(item) { list += item.id + ','; });
  <%= remote_function(:url => { :controller => :events, :action => :create}, :with => "'ids=' + list" ) %>
<% end %>

次に、これらの列のコンマ区切りIDをDBにインポートするためのレーキタスクを作成しました。これは翌日に実行されます:

desc "Calculate impressions"
task :count_impressions => :environment do
  date = ENV['DATE'] || (Date.today - 1).to_s # defaults to yesterday (yyyy-mm-dd)
  file = File.new("log/impressions/#{date}.log", "r")
  item_impressions = {}
  while (line = file.gets)
    ids_string = line.split(' ')[1]
    next unless ids_string
    ids = ids_string.split(',')
    ids.each {|i| item_impressions[i] ||= 0; item_impressions[i] += 1 }
  end
  item_impressions.keys.each do |id|
    ActiveRecord::Base.connection.execute "insert into item_stats(item_id, impression_count, collected_on) values('#{id}',#{item_impressions[id]},'#{date}')", 'Insert Item Stats'
  end

  file.close
end

注意すべきことの1つは、ロガー変数がコントローラーアクションで宣言されています - 環境ではなく、通常はロガーで行うように。私はこれをベンチマークしました-10000の執筆には約20秒かかりました。平均で約2ミリ秒の書き込み。 Envirnment.RBにファイル名があると、約14秒かかりました。このトレードオフを行い、ファイル名を動的に決定できるようにしました。これは、真夜中にファイルを切り替える簡単な方法です。

この時点での私たちの主な関心事 - 1日あたりの異なるアイテムの数が何度もカウントされるのかわかりません - すなわち。尾の長さはわかりません。これにより、毎日DBに追加される行の数が決まります。毎日のレポートを維持し、その時点でさらに結果をさらに役立たせるかを制限する必要があると期待しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top