【问题标题】:CQRS - How do I handle a user viewing a page or queryCQRS - 如何处理查看页面或查询的用户
【发布时间】:2012-11-18 19:58:03
【问题描述】:

我正在将 CQRS 用于我正在构建的应用程序(具有复杂业务逻辑的在线讨论系统),并且我在实现中遇到了让我担心的部分。

我应该如何处理综合浏览量?如果用户查看线程,我想跟踪它。因为我想跟踪它,所以我应该创建一个命令和一个事件,并将其绑定到负责我正在查看的对象的聚合根(例如,分别为 UserViewsThread 和 UserViewedThread)。但这似乎效率很低——除此之外,没有理由在讨论系统的许多用例(查看论坛/线程)中找到聚合根。既然我要介绍这一点,我将在页面的每个视图上都有一个额外的命令调度和事件发布,这反过来又负责“后台处理”线程聚合、序列化我的事件并将其发送到我的事件出版商。

必须有更好的方法来做到这一点。我在考虑也许让我的控制器对象能够调度事件 - 但是通过绕过我的聚合,我不能再将行为附加到页面浏览量。

另一种可能性是使用它作为验证我的用户的一种方式。将允许 UserViewsThread 和 UserViewsForum 命令引发身份验证异常,以让我的控制器知道用户无法执行此操作。但是,如果要将这些转换为事件并存储在我的事件存储中,那么我们正在讨论在每个页面视图上创建的多个事件 - 这很可能会破坏性能(每个页面视图都会导致数据库事务...呃)和资源管理。

你男朋友的想法是什么?

【问题讨论】:

    标签: c# design-patterns cqrs event-sourcing


    【解决方案1】:

    使用 CQRS 并不意味着与应用程序的每一个微小交互——尤其是与基础设施相关的——都必须传递命令/事件链。跟踪浏览量是一个跨领域的问题,可以很容易地单独实施。

    只需让读取层中的查询在每次调用时为某个表中的各个视图模型增加一个计数器

    一旦您开始创建每次调用查询时都会改变状态的命令,您将再次紧密耦合读写,命令/查询分离的全部好处将付诸东流。您首先使用 CQRS 来区分这两个问题。

    【讨论】:

    • 值得一提的是,如果每次页面浏览都会产生一个事件,那么聚合根可能存在严重的并发问题。 OP 应该使用 statsd 进行跟踪,因为它非常快 - 您可以在幕后处理您的页面视图并根据收集的数据更新域模型。
    【解决方案2】:

    您可以在会话中捕获跟踪信息并偶尔将其发送到服务器。

    此外,您为什么认为您真的需要一个带有事件存储的 AR 来跟踪这些信息?我会在一些基于状态的存储中聚合这些信息。

    【讨论】:

    • 嗯,用户查看的内容在报告中可能非常重要。如果我的报告基础架构使用事件存储将事件回复到我的读取模型中,那么我将能够根据特定查询的用户视图构建更精细的报告。
    • 我个人更喜欢只使用谷歌分析来跟踪访问。
    【解决方案3】:

    我们所做的几乎与此相同。但是像这样跟踪所有内容感觉不对,您的读取应该很快并且不需要进行任何写入。

    我们最终为所有事件添加了一个跟踪对象,但我认为我不会再这样做了。我会考虑编写一些javascript,就像谷歌分析一样,并从前端创建一个单独的命令。

    另外,我会将您的跟踪队列和正常队列分开。

    【讨论】:

      【解决方案4】:

      它似乎是一个网络应用程序,所以我将创建一个属性 (asp.net mvc/WebApi) 来处理页面视图。当然,该属性只会调用 INFRASTRUCTURE 服务(因为我认为跟踪统计信息不是域的一部分),它只会更新存储中的页面视图。简单来说,服务调用一个更新持久化的 Dao(update Posts set pageviews=pageviews+1)。

      当然,该属性可以只发送异步命令来更新页面视图,该命令将在后台执行,因此“写入”实际上不会干扰读取。

      如果您的应用程序有/将有大量流量,那么我建议采用以下持久性策略:有一个表 PageViews(PageId,ViewsNumber,TimeStamp),您只需在其中为每个页面视图附加一行。然后每隔 X 分钟,有一个后台服务将执行 Sum(ViewsNumber) GroupBy(PageId) where TimeStamp> oldTimestamp。您不会在毫秒内获得统计信息,但它们会经常更新,并且应用会保持响应。

      除了您正在构建分析系统的情况外,我不认为此问题属于任何领域的一部分,因此您不需要 AR、DDD 或事件溯源。对于您的情况,页面统计信息是附加到页面的信息,而不是页面的一部分。它们仅在您实际在同一视图中显示它们的读取模型中被一起考虑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多