简短的答案是,只有新数据通过网络发送。运作方式如下。
Meteor服务器的三个重要部分用于管理订阅:publish函数,它定义订阅提供哪些数据的逻辑;的蒙戈驱动器,其手表更改数据库中; 与合并盒,它结合了所有客户的活动订阅,然后再将它们通过网络客户端。
发布功能
每当Meteor客户端订阅一个集合时,服务器都会运行
publish函数。发布功能的工作是找出其客户端应具有的文档集,并将每个文档属性发送到合并框中。它为每个新的订阅客户端运行一次。您可以将任何所需的JavaScript放入发布函数中,例如使用任意复杂的访问控制this.userId
。publish函数通过调用将数据发送到合并框中this.added
,this.changed
和
this.removed
。有关更多详细信息,请参见
完整的发布文档。
大多数的发布功能,没有淤泥与周围的低级别
added
,changed
和removed
API,虽然。如果发布函数返回一个蒙戈光标,流星服务器自动连接蒙戈驱动器的输出(insert
,update
,和removed
回调)到合并框的输入(this.added
,this.changed
和this.removed
)。您可以在发布功能中预先进行所有权限检查,然后将数据库驱动程序直接连接到合并框,而无需任何用户代码,这非常干净。启用自动发布功能后,即使隐藏了这一点,服务器也会自动为每个集合中的所有文档设置查询,并将其推入合并框。
另一方面,您不仅限于发布数据库查询。例如,您可以编写发布功能,从发布商内部的设备读取GPS位置Meteor.setInterval
,或从另一个Web服务轮询旧式REST API。在这种情况下,你会通过调用低级别发出更改合并盒added
,changed
和removed
DDP API。
Mongo司机
该蒙戈司机的工作是看Mongo的数据库更改到现场查询。这些查询会连续运行,并通过调用added
,随着结果的更改返回更新。removed
和changed
回调。
Mongo不是实时数据库。因此,驱动程序轮询。它为每个活动的实时查询保留最后查询结果的内存副本。在每个轮询周期中,它会将新结果与先前保存的结果进行比较,计算出的最小集added
,removed
和changed
事件描述的差别。如果多个调用者为同一个实时查询注册了回调,则驱动程序仅监视该查询的一个副本,并以相同的结果调用每个已注册的回调。
每次服务器更新集合时,驱动程序都会重新计算该集合上的每个实时查询(未来版本的Meteor将公开一个扩展API,以限制更新时重新计算哪些实时查询。)驱动程序还会在10秒计时器上轮询每个实时查询,以查询捕获绕过Meteor服务器的带外数据库更新。
合并框
在的工作合并盒是将结果合并(added
,changed
和removed
所有的客户的主动发布功能的调用)到一个单一的数据流。每个连接的客户端都有一个合并框。它拥有客户端minimongo缓存的完整副本。
在您只有一个订阅的示例中,合并框本质上是传递。但是,更复杂的应用程序可以具有多个可能重叠的订阅。如果两个订阅都在同一文档上设置了相同的属性,则合并框将决定哪个值具有优先级,并将其仅发送给客户端。我们尚未公开用于设置订阅优先级的API。目前,优先级由客户端订阅数据集的顺序确定。客户端进行的第一个订阅具有最高优先级,第二个订阅具有第二高的优先级,依此类推。
因为合并框保留了客户端的状态,所以无论发布功能如何发送,合并框都可以发送最少的数据以使每个客户端保持最新状态。
更新时会发生什么
因此,现在我们为您的方案奠定了基础。
我们有1,000个关联的客户。每个订阅了相同的实时Mongo查询(Somestuff.find({})
)。由于每个客户端的查询都相同,因此驱动程序仅运行一个实时查询。有1,000个活动合并框。并且每个客户的发布功能在实时查询中注册了added
,changed
和
removed
,该实时查询输入到合并框之一中。没有其他任何连接到合并框。
首先是Mongo司机。当一个客户将一个新文档插入时Somestuff
,它将触发重新计算。Mongo驱动程序针对所有文档重新运行查询Somestuff
,将结果与内存中的前一个结果进行比较,发现有一个新文档,并分别调用1,000个注册的insert
回调。
接下来,发布功能。这里几乎没有发生什么:1,000个insert
回调中的每个回调都通过调用将数据推送到合并框中added
。
最后,每个合并框都会根据其客户端缓存的内存副本检查这些新属性。在每种情况下,它都会发现这些值尚未出现在客户端上,并且不会遮盖现有的值。因此,合并框DATA
在与其客户端的SockJS连接上发出DDP 消息,并更新其服务器端内存中副本。
CPU总成本是进行一个Mongo查询的成本,再加上1,000个合并框的成本,这些合并框用于检查其客户端的状态并构造新的DDP消息有效负载。流经网络的唯一数据是发送到1,000个客户端中的每个客户端的一个JSON对象(对应于数据库中的新文档),以及从原始插入到客户端的一条RPC消息到服务器。
最佳化
这是我们绝对计划的。
更高效的Mongo驱动程序。我们
在0.5.1中优化了驱动程序,以使每个不同的查询仅运行一个观察者。
并非每个数据库更改都应触发重新计算查询。我们可以进行一些自动化的改进,但是最好的方法是让开发人员指定需要重新运行哪些查询的API。例如,对于开发人员来说显而易见的是,将消息插入一个聊天室不应使对第二个房间中的消息的实时查询无效。
Mongo驱动程序,发布功能和合并框不需要在同一进程中甚至在同一台机器上运行。一些应用程序运行复杂的实时查询,并且需要更多的CPU来监视数据库。其他人只有几个截然不同的查询(想象一个博客引擎),但是可能有许多连接的客户端-这些需要更多的CPU用于合并框。分离这些组件将使我们能够独立缩放每个组件。
许多数据库支持在更新行时触发并提供旧行和新行的触发器。使用该功能,数据库驱动程序可以注册触发器,而不用轮询更改。