一个应用正在使用 meteor-redis
包来运行 redis 查询,有时可能需要 30 秒才能返回 100k 个结果。在这段等待时间内,Meteor 在等待查询结果时卡住并占用 100% 的 CPU。
var client = redis.createClient(port, url)
client.zrangebyscoreSync = Meteor._wrapAsync(client.zrangebyscore)
client.zrangebyscoreSync(['game:scores', '', '+inf'], function(err, scores) {
_.each(scores, function(score, player) {
var doc = { ... }
Scores.insert(doc)
})
})
问题:有没有办法让Meteor在等待redis返回庞大数据集的同时做点别的事情?如果 client.zrangebyscore
没有用 Meteor._wrapAsync
包裹,Meteor 会抛出错误
Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.
跟踪将其指向 Scores.insert(doc)
行。
最佳答案
一般来说,Meteor 将允许其他方法运行,前提是您首先在它们上运行 this.unblock()
,从而将这些请求旋转到新的纤程中。
CPU 使用率达到 100% 的原因可能是 cpu 空闲纤程的类型和下面正在执行的任务的组合。
如果这是一个问题,您可以尝试改用 Meteor.bindEnvironment,它不会使用 future 等待,并且仍然使用回调来确保一切保持畅通:
client.zrangebyscore(['game:scores', '', '+inf'], Meteor.bindEnvironment(function(err, result) {
_.each(scores, function(score, player) {
var doc = { ... }
Scores.insert(doc)
})
}));
Meteor bindEnvironment 几乎与 Meteor._wrapAsync 相同,除了它缺少等待结果的部分。看起来你没有使用这个位,因为你没有寻找来自 client.zrangebyscoreSync
的结果。 Meteor.bindEnvironment 可能更适合这种用途,它将您的回调包装在 Fiber 中,因此您可以在其中使用 Meteor 代码。
关于javascript - Meteor._wrapAsync 导致 100% CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24635108/