benchmarking - Meteor 在众多客户之间共享大量收藏时的效率如何?

标签 benchmarking meteor

想象一下以下案例:

  • 1,000 个客户端连接到 Meteor 页面,显示“Somestuff”集合的内容。
  • “Somestuff”是一个包含 1,000 件物品的集合。
  • 有人在“Somestuff”集合中插入了一个新项目

  • 会发生什么:
  • 全部 Meteor.Collection客户端上的 s 将被更新,即插入转发给所有客户端(这意味着一个插入消息发送给 1,000 个客户端)

  • 服务器确定需要更新哪个客户端的 CPU 成本是多少?

    只有插入的值才会转发给客户端,而不是整个列表,这是否准确?

    这在现实生活中如何运作?是否有任何可用的此类规模的基准或实验?

    最佳答案

    简短的回答是只有新数据才能通过网络发送。这是
    它是如何工作的。

    Meteor 服务器的三个重要部分负责管理
    订阅:发布函数,它定义了什么的逻辑
    订阅提供的数据; Mongo 驱动程序,它监视
    更改数据库;和合并框,它结合了所有
    客户端的事件订阅并通过网络将它们发送到
    客户。

    发布功能

    每次 Meteor 客户端订阅一个集合时,服务器都会运行一个
    发布功能。发布函数的工作是找出集合
    其客户应拥有的文档并发送每个文档属性
    进入合并框。它为每个新订阅客户端运行一次。你
    可以在发布函数中放入任何你想要的 JavaScript,比如
    使用 this.userId 进行任意复杂的访问控制.发布
    函数通过调用 this.added 将数据发送到合并框, this.changedthis.removed .见
    full publish documentation对于
    更多细节。

    大多数发布功能不必处理低级added , changedremoved API,不过。如果发布函数返回一个 Mongo
    cursor, meteor 服务器自动连接Mongo的输出
    驱动程序( insertupdateremoved 回调)到
    合并框( this.addedthis.changedthis.removed )。它很整洁
    您可以在发布功能中预先进行所有权限检查,并且
    然后直接将数据库驱动连接到合并框,无需任何用户
    代码的方式。当自动发布打开时,即使是这一点
    hidden:服务器自动为每个文档中的所有文档设置一个查询
    集合并将它们推送到合并框中。

    另一方面,您不仅限于发布数据库查询。
    例如,您可以编写一个读取 GPS 位置的发布函数
    来自 Meteor.setInterval 内的设备,或轮询旧的 REST API
    来自另一个网络服务。在这些情况下,您将更改
    通过调用低级合并框added , changedremoved DDP API。

    蒙戈司机

    Mongo 驱动程序的工作是观察 Mongo 数据库中的更改
    实时查询。这些查询持续运行并返回更新作为
    调用 added 更改结果, removed , 和 changed回调。

    Mongo 不是实时数据库。所以司机投票。它保持一个
    每个事件实时查询的最后一个查询结果的内存副本。开
    每个轮询周期,它将新结果与之前保存的结果进行比较
    结果,计算最小集合added , removed , 和 changed描述差异的事件。如果多个调用者注册
    同一个实时查询的回调,驱动程序只观看一份
    查询,使用相同的结果调用每个注册的回调。

    每次服务器更新一个集合时,驱动程序都会重新计算每个
    对该集合的实时查询(Meteor 的 future 版本将公开一个
    用于限制哪些实时查询在更新时重新计算的扩展 API。)
    驱动程序还会在 10 秒的计时器上轮询每个实时查询以捕获
    绕过 Meteor 服务器的带外数据库更新。

    合并框

    合并框的工作是合并结果( addedchangedremoved调用)所有客户端的事件发布功能到单个数据中
    流。每个连接的客户端都有一个合并框。它拥有一个
    客户端 minimongo 缓存的完整副本。

    在您只有一个订阅的示例中,合并框是
    本质上是一种传递。但是一个更复杂的应用程序可以有多个
    可能重叠的订阅。如果两个订阅都设置了
    同一文档上的相同属性,合并框决定哪个值
    优先并且只将它发送给客户端。我们没有曝光
    用于设置订阅优先级的 API。目前,优先事项是
    由客户端订阅数据集的顺序决定。第一个
    客户订阅的优先级最高,第二个
    订阅是次高的,依此类推。

    因为合并框保存了客户端的状态,所以它可以发送最少的
    保持每个客户端最新的数据量,无论发布什么
    功能喂养它。

    更新时会发生什么

    所以现在我们已经为您的场景做好了准备。

    我们有 1,000 个连接的客户端。每个人都订阅了同一个直播
    Mongo 查询 ( Somestuff.find({}) )。由于每个客户端的查询都相同,因此驱动程序是
    只运行一个实时查询。有 1,000 个事件合并框。并且
    每个客户端的发布函数都注册了一个 added , changed ,和removed在进入合并框之一的实时查询上。
    没有其他任何东西连接到合并框。

    首先是 Mongo 驱动程序。当其中一个客户端插入新文档时
    进入 Somestuff ,它会触发重新计算。 Mongo 驱动程序重新运行
    查询 Somestuff 中的所有文档,将结果与
    内存中的先前结果,发现有一个新文档,并且
    调用 1,000 个已注册的每一个 insert回调。

    接下来,发布功能。这里几乎没有发生:每个
    的 1,000 insert回调通过以下方式将数据插入合并框
    调用 added .

    最后,每个合并框对照其检查这些新属性
    其客户端缓存的内存副本。在每种情况下,它发现
    值尚未在客户端上,并且不影响现有值。所以
    合并框发出 DDP DATA SockJS 连接到其的消息
    客户端并更新其服务器端内存副本。

    总 CPU 成本是 diff 一个 Mongo 查询的成本,加上
    1,000 个合并框检查其客户的状态并构建一个新的
    DDP 消息负载。唯一通过线路流动的数据是单个
    JSON 对象发送到 1,000 个客户端中的每一个,对应于新的
    数据库中的文档,加上一条从服务器发送到服务器的 RPC 消息
    进行原始插入的客户。

    优化

    这是我们绝对计划好的。

  • 更高效的 Mongo 驱动程序。我们
    optimized the driver
    在 0.5.1 中,每个不同的查询只运行一个观察者。
  • 并非每个数据库更改都应触发查询的重新计算。我们
    可以进行一些自动化改进,但最好的方法是 API
    这让开发人员可以指定哪些查询需要重新运行。对于
    例如,对于开发人员来说,将消息插入到
    一个聊天室不应使对消息的实时查询无效
    第二个房间。
  • Mongo 驱动程序、发布函数和合并框不需要运行
    在同一进程中,甚至在同一台机器上。一些应用
    运行复杂的实时查询并且需要更多 CPU 来观察数据库。
    其他人只有几个不同的查询(想象一个博客引擎),但是
    可能有很多连接的客户端——这些需要更多的 CPU 来合并
    盒子。分离这些组件将让我们缩放每个部分
    独立。
  • 许多数据库支持在更新行时触发的触发器,并且
    提供旧行和新行。有了这个特性,一个数据库驱动程序
    可以注册触发器而不是轮询更改。
  • 关于benchmarking - Meteor 在众多客户之间共享大量收藏时的效率如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13113256/

    相关文章:

    python - 在这个简单的例子中,为什么 Matlab 看起来比 Python 慢得多

    c - 全局变量性能效果(c、c++)

    javascript - 在哪里可以找到 Meteor 模板事件列表?

    mongodb - 蒙戈 : Meteor isn't running a local MongoDB server

    error-handling - 错误登录处理 meteor

    javascript - meteor react 订阅

    C正则表达式性能

    Scala 标准等效

    python - PyPy 比 Python 快 17 倍。 Python可以加速吗?

    javascript - 插入/更新到具有未确认写入问题的 Meteor 集合