如何知道我不使用mongodb操作阻止Ruby eventmachine

如何知道我不使用mongodb操作阻止Ruby eventmachine,ruby,mongodb,asynchronous,eventmachine,Ruby,Mongodb,Asynchronous,Eventmachine,我正在开发一个基于eventmachine的应用程序,它定期轮询MongoDB存储文档的更改 简化的代码段可能如下所示: require 'rubygems' require 'eventmachine' require 'em-mongo' require 'bson' EM.run { @db = EM::Mongo::Connection.new('localhost').db('foo_development') @posts = @db.collectio

我正在开发一个基于eventmachine的应用程序,它定期轮询MongoDB存储文档的更改

简化的代码段可能如下所示:

require 'rubygems'
require 'eventmachine'
require 'em-mongo'
require 'bson'

EM.run {

  @db       = EM::Mongo::Connection.new('localhost').db('foo_development')
  @posts    = @db.collection('posts')
  @comments = @db.collection('comments')

  def handle_changed_posts
    EM.next_tick do
      cursor = @posts.find(state: 'changed')
      resp = cursor.defer_as_a

      resp.callback do |documents|
        handle_comments documents.map{|h| h["comment_id"]}.map(&:to_s) unless documents.length == 0
      end

      resp.errback do |err|
        raise *err
      end
    end
  end

  def handle_comments comment_ids
    meta_product_ids.each do |id|
      cursor = @comments.find({_id: BSON::ObjectId(id)})
      resp = cursor.defer_as_a

      resp.callback do |documents|
        magic_value = documents.first['weight'].to_i * documents.first['importance'].to_i
      end

      resp.errback do |err|
        raise *err
      end
    end
  end

  EM.add_periodic_timer(1) do
    puts "alive: #{Time.now.to_i}"
  end

  EM.add_periodic_timer(5) do
    handle_changed_posts
  end
}
因此EM每5秒迭代一次所有帖子,并选择修改过的帖子。对于每个更改的帖子,它将注释id存储在一个数组中。完成后,该数组被传递给
句柄\u comments
,该句柄加载每个注释并进行一些计算

现在我在理解上有一些困难:

  • 我知道,在一个有20000篇帖子的Rails控制台中,这个加载帖子->加载评论->计算周期需要3秒钟,因此,在EM中不会更快。我计划每5秒使用
    handle\u changed\u posts
    方法,这很好,除非POST数量增加,并且计算所需时间超过5秒,然后再次计划相同的运行。那样的话,我很快就会有问题了。如何避免这种情况

  • 我相信em mongo,但我不相信我的em知识。要监视EM仍在运行,我将每秒放置一个时间戳。这似乎工作得很好,但当我的计算运行时,每5秒就有一点颠簸。这是我阻止循环的信号吗

  • 有没有什么方法可以确定我是否阻止了循环

  • 我是否应该使用-19来优化我的eventmachine进程,使其始终成为顶级OS prio


  • 我一直不愿意在这里回答,因为到目前为止我还没有mongo的经验,但考虑到没有人回答,这里的一些东西是一般EM的东西,我可能能够帮助:

  • 在第一次扫描结束时安排下一次扫描(
    resp.callback
    resp.errback
    中的
    handle\u changed\u posts
    似乎很适合链接下一次扫描),可以使用
    add\u timer
    next\u tick
  • 也许,尝试更频繁地处理mongo跳闸,以便它们处理更小的数据块。反应堆内的任何cpu周期占用都会使反应堆循环太忙,无法接受诸如周期性计时器滴答声之类的事件
  • 没有简单的方法,没有。一个想法是测量
    时间的差异。现在
    下一次{Time.now}
    ,进行基准测试,然后在差异超过阈值时跟踪可能的罪魁祸首。模拟慢速查询(?)和许多并行连接是一个好主意
  • 我真的不知道,我从来没有遇到过这样的人,我想这取决于服务器上运行的其他东西

  • 为了扩展bbozo的答案,特别是关于第二个问题,当您运行代码时,您没有时间不阻塞循环。根据我的经验,当我们谈论“非阻塞”代码时,我们真正的意思是“不会阻塞很长的代码”。通常,这些都是非常短的时间段(小于一毫秒),但它们在执行时仍然会阻塞

    此外,
    下一步真正做的事情就是说“做这个,但不要现在”。正如bbozo所提到的,您真正想要做的是将您的处理分成多个刻度,这样每个迭代块的时间就越短越好

    要使用您自己的基准测试,如果20000条记录需要大约3秒的时间来处理,那么4000条记录应该需要大约0.6秒。这足够短,通常不会影响你的1秒心跳。您可以将其进一步拆分,以减少阻塞量并使反应器运行更平稳,但这实际上取决于您需要从反应器获得多少并发性