gpt4 book ai didi

ruby-on-rails - Rails 中的报告生成设计模式?

转载 作者:行者123 更新时间:2023-12-04 02:28:35 26 4
gpt4 key购买 nike

我正在一个应用程序中构建多个报告,并且遇到了几种构建报告的方法,并希望了解构建可扩展且尽可能实时的报告的最佳/常用方法。

首先,一些条件/限制/目标:

  • 报告应该能够实时处理(使用 node.js 或 ajax 轮询)
  • 报告应该以优化的方式更新
  • 如果报告是关于页面浏览量的,并且您每秒获得数千次浏览量,则最好不要在每次页面浏览时更新报告,但可能每 10 或 100 次。
  • 但它应该仍然接近实时(因此每天/每小时的 cron 不是可接受的替代方案)。
  • 报告不应该重新计算它已经计算过的东西。
  • 如果它有计数,它会增加一个计数器。
  • 如果它有平均值,也许它可以以某种方式更新平均值,而无需抓取它每秒平均的所有记录并重新计算(尚不确定如何执行此操作)。
  • 如果它有一个日期范围(今天、last_week、last_month 等)的计数/平均值,并且它是实时的,它不应该每秒/请求重新计算这些平均值,以某种方式只执行最少的操作。
  • 如果报告是关于记录的,并且记录的“生命周期”是完整的(比如一个 Project ,项目持续了 6 个月,有一堆事件,但现在已经结束了),报告应该永久保存以便后续检索只需拉出一个预先计算好的文档。

  • 报告不需要可搜索,因此一旦数据在文档中,我们就只是显示文档。客户端基本上会得到一个 JSON 树,表示所有的统计数据、图表等,因此它可以在 Javascript 中呈现。

    我的问题出现是因为我想找出一种方法来做 大型数据集的实时报告 .

    假设我要报告网站上的整体用户注册和事件。该网站有 100 万用户,平均每秒有 1000 次页面浏览。有一个 User模型和 PageView模型比方说,其中 User has_many :page_views .假设我有这些统计数据:
    report = {
    :users => {
    :counts => {
    :all => user_count,
    :active => active_user_count,
    :inactive => inactive_user_count
    },
    :averages => {
    :daily => average_user_registrations_per_day,
    :weekly => average_user_registrations_per_week,
    :monthly => average_user_registrations_per_month,
    }
    },
    :page_views => {
    :counts => {
    :all => user_page_view_count,
    :active => active_user_page_view_count,
    :inactive => inactive_user_page_view_count
    },
    :averages => {
    :daily => average_user_page_view_registrations_per_day,
    :weekly => average_user_page_view_registrations_per_week,
    :monthly => average_user_page_view_registrations_per_month,
    }
    },
    }

    我尝试过的事情:

    1.哪里 UserPageView都是 ActiveRecord 对象,所以一切都通过 SQL。

    我将所有用户分块抓取,如下所示:
    class User < ActiveRecord::Base
    class << self
    def report
    result = {}
    User.find_in_batches(:include => :page_views) do |users|
    # some calculations
    # result[:users]...
    users.each do |user|
    # result[:users][:counts][:active]...
    # some more calculations
    end
    end
    result
    end
    end
    end

    2. 两条记录都是 MongoMapper::Document对象

    Map-reduce 在现场计算真的很慢,我还没有花时间弄清楚如何使这项工作具有实时性(查看 hummingbird)。基本上我做同样的事情:将记录分块,将结果添加到散列中,就是这样。

    3. 每个计算都是它自己的 SQL/NoSQL 查询

    这是 Rails 的一种方法 statistics gem需要。我唯一不喜欢的是这可能产生的查询量(还没有对每个请求每个报告进行 30 个查询进行基准测试是否比将所有对象分块到内存中并直接用 ruby​​ 排序更好)



    我猜的问题是,根据您的经验,对大型数据集进行实时报告的最佳方法是什么?通过在每个请求中对内存中的记录进行分块/排序(我现在正在做的事情,我可以使用 hourly-cron 进行一些优化,但它不是实时的),报告需要大约一秒钟来生成(复杂的日期公式和这样),有时更长。

    除了传统的优化(更好的日期实现、sql/nosql 最佳实践),我在哪里可以找到一些关于构建报告的实用且经过验证的文章?我可以建立报告没问题,问题是,你如何使它快速、实时、优化,对吗?真的什么都没发现

    最佳答案

    为您的用例构建近乎实时的报告的最简单方法是使用缓存。

    所以在report方法中,你需要使用rails cache

    class User < ActiveRecord::Base
    class << self
    def report
    Rails.cache.fetch('users_report', expires_in: 10.seconds) do
    result = {}
    User.find_in_batches(:include => :page_views) do |users|
    # some calculations
    # result[:users]...
    users.each do |user|
    # result[:users][:counts][:active]...
    # some more calculations
    end
    end
    result
    end
    end
    end
    end

    在客户端,您只需使用 ajax 池请求此报告。这样生成报告就不会成为瓶颈,因为生成它们需要大约 1 秒,而且许多客户可以轻松获得最新结果。

    为了获得更好的用户体验,您可以在两个报告之间存储增量并使用此增量预测在客户端增加您的报告,如下所示:
    let nextPredictedReport = null;
    let currentReport = null;

    const startDrawingPredicted = () => {
    const step = 500;
    const timePassed = 0;
    setInterval(() => {
    timePassed += step;
    const predictedReport = calcDeletaReport(currentReport, nextPredictedReport, timePassed);
    drawReport(predictedReport);
    }, step);
    };

    setInterval(() => {
    doReportAjaxRequest().then((response) => {
    drawReport(response.report);
    currentReport = response.report;
    nextPredictedReport = response.next_report;
    startDrawingPredicted();
    });
    }, 10000);

    这只是该方法的一个示例, calcDeletaReportdrawReport应该自己实现 + 这个解决方案可能有问题,因为它只是一个想法:)

    关于ruby-on-rails - Rails 中的报告生成设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4728222/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com