【问题标题】:Meteor._wrapAsync causes 100% CPUMeteor._wrapAsync 导致 100% CPU
【发布时间】:2014-08-29 09:10:59
【问题描述】:

一个应用正在使用 meteor-redis 包运行 redis 查询,有时可能需要 30 秒才能返回 10 万个结果。在这段等待时间内,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) 行。

【问题讨论】:

标签: javascript node.js meteor redis node-redis


【解决方案1】:

一般来说,Meteor 将允许其他方法运行,前提是您先在它们上运行 this.unblock(),从而将这些请求转入新的纤程。

您获得 100% 的 CPU 使用率的原因可能是 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 代码。

【讨论】:

  • client.zrangebyscsore 返回的 scores 正在被 _.each 使用。我们还能用Meteor.bindEnvironment吗?
  • @Nyxynyx 应该没问题。我有点不确定究竟是什么让你脱离了光纤(除了 setTimeout),我认为它使用了本地节点方法,如 request 和 fs 等。如果它像forEach 这样应该没问题。更新 - 刚刚检查了它的来源,应该没问题,因为它使用 .call 绑定回调或使用 forEach 在引擎盖下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 2019-01-14
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多