【发布时间】:2012-08-31 04:31:12
【问题描述】:
我有一个包含 6000 只股票的 1000 万个文档的集合,股票名称被索引。当我订阅一只新股时,流星挂了10多秒,就得到了这只股票的大约3000份文件。同样在认购几只股票后,流星以 100% 的 cpu 使用率挂起。同步“大”集合时,流星看起来真的很慢。实际上我的应用程序只是只读的。我想知道是否有办法为只读客户端加速流星?我还想知道为每只股票创建一个单独的集合是否有帮助?
【问题讨论】:
标签: meteor
我有一个包含 6000 只股票的 1000 万个文档的集合,股票名称被索引。当我订阅一只新股时,流星挂了10多秒,就得到了这只股票的大约3000份文件。同样在认购几只股票后,流星以 100% 的 cpu 使用率挂起。同步“大”集合时,流星看起来真的很慢。实际上我的应用程序只是只读的。我想知道是否有办法为只读客户端加速流星?我还想知道为每只股票创建一个单独的集合是否有帮助?
【问题讨论】:
标签: meteor
虽然这是一个规模问题,并且可能可以改进;应该注意的是,您为您的任务使用了错误的技术,因为 Meteor 用于客户端之间的交互,而不是用于检索大量只读时间敏感数据。虽然状态跟踪屏幕可能仍然有些意义,但大量时间关键数据肯定不会...
整个 Meteor 堆栈在任何本机堆栈中的简单实现都引入了极大的开销;老实说,我什至会考虑 Java 或 C# 会引入的开销,并在选择 Java 或 C# 和 PHP 和 C++ 等低级语言时三思而后行。 Ruby、Python、Node.js 等语言确实是另一回事。它们是为快速原型设计而设计的,但就延迟/吞吐量而言,由于 JIT 所需的开销,它们落后了,不要忘记一些非本地处理方法所增加的开销。
TL;DR:为工作使用正确的工具,否则你会割伤手指......
【讨论】:
我喜欢流星的简单。我只是停止使用本地 mongodb 集合以避免同步开销,性能看起来非常好。
Meteor.default_connection.registerStore "prices",
beginUpdate: ->
update: (msg) ->
updateChart(msg.set)
endUpdate: ->
reset: ->
对于新流星,下面的作品。
Meteor.default_connection.registerStore collection,
constructor: (@update) ->
# Called at the beginning of a batch of updates.
beginUpdate: ->
update: (msg) ->
update(msg.fields, msg.id) if msg.fields
endUpdate: ->
reset: ->
【讨论】:
Meteor 正在将整个数据集推送到您的客户端。
您可以通过删除自动发布包来关闭自动发布:
meteor remove autopublish
然后为您的客户创建特定的特定订阅。
当您订阅时,您可以将会话变量作为参数传递,因此在客户端上您可以执行以下操作:
sub = new Meteor.autosubscribe(function(){
Meteor.subscribe('channelname', getSession('filterval'));
}
在服务器上,您使用参数来过滤发送到客户端的结果集,这样您就不会一次通过管道传输所有内容。您可以使用过滤器以某种方式对数据进行分段。
Meteor.publish('channelname', function(filter){
return Collection.find({field: filter});
}
现在,每当您使用 setSession('filterval', 'newvalue'); 更改客户端上的 filterval 时,订阅将自动更改,并将新数据集发送到客户端。
您可以使用它来控制发送给客户端的数据量和数据量。
正如另一位发帖人所说,你真的要问这是否是这项工作的最佳工具。 Meteor 适用于在(可能)两个方向上实时更新的相对较小的数据集。它经过高度优化,并为该用例提供了大量的脚手架。
对于另一个用例(例如只读的大型数据集),它可能没有意义。它有很多开销来提供您不会使用的功能,并且您将编写代码以获得您需要的功能。
【讨论】:
启用自动发布后,您可能会看到 Mongodb 中的大量文档集合会降低性能。您可以通过删除自动发布并编写代码以仅发布相关数据而不是整个数据库来解决此问题。
文档还涉及手动管理缓存:
老练的客户可以打开和关闭订阅,以控制如何 大量数据保存在缓存中并管理网络流量。当一个 订阅已关闭,其所有文档都将从 缓存,除非同一个文档也由另一个活动提供 订阅。
目前正在对 Meteor 进行其他性能改进,包括支持“大量客户端”的 DDP 级代理。你可以在 Meteor roadmap 看到更多细节。
【讨论】:
我在同样的问题上苦苦挣扎。就我而言,我只需要同步大约 3000 条记录,总共大约 30KB。经过数周的尝试,我最终意识到同步不是问题,而是同步时发生的 LiveHTML 更新。
通过在初始页面加载期间禁用模板更新,我能够将 300 条(过滤的)记录的页面加载时间从 10 秒减少到所有 3000 条记录的不到 2 秒。我通过向定义模板内容的函数添加条件来实现这一点:
之前(服务器发布 300 条记录的 10 秒页面加载):
Template.itemlist.items = function () {
return Item.find({type: 'car'},
{sort: {start: -1},
limit: 30});
};
至(服务器发布的 3000 条记录的 2 秒页面加载):
Template.itemlist.items = function () {
if (Session.get("active")) {
return Item.find({type: 'car'},
{sort: {start: -1},
limit: 30});
} else {
return [];
}
};
为了仅在加载数据后“激活”会话,我添加了:
Deps.autorun(function () {
Meteor.subscribe("Item",
{
onReady: function() {
Session.set("active", true);
}
});
});
【讨论】: