异步读取EventMachine中的文件

时间:2011-10-14 18:38:21

标签: ruby file asynchronous cassandra eventmachine

我正在使用Ruby EventMachines已经有一段时间了,我认为我理解它的基础知识。

但是,我不确定如何在大文件(120 MB)中正常读取。我的目标是逐行读取文件并将每一行写入Cassandra数据库(同样应该使用MySQL,PostgreSQL,MongoDB等,因为Cassandra客户端显式支持EM)。简单的片段阻塞了反应堆,对吗?

require 'rubygems'
require 'cassandra'
require 'thrift_client/event_machine'

EM.run do
  Fiber.new do
    rm = Cassandra.new('RankMetrics', "127.0.0.1:9160", :transport => Thrift::EventMachineTransport, :transport_wrapper => nil)
    rm.clear_keyspace!
    begin
      file = File.new("us_100000.txt", "r")
    while (line = file.gets)
      rm.insert(:Domains, "#{line.downcase}", {'domain' => "#{line}"})
    end
      file.close
    rescue => err
      puts "Exception: #{err}"
      err
    end
    EM.stop
  end.resume
end

但是,以异步方式读取文件的正确方法是什么?

2 个答案:

答案 0 :(得分:5)

EventMachine中没有异步文件IO支持,实现您尝试执行的操作的最佳方法是在每个tick上读取几行并将其发送到数据库。最重要的是不要读太大的块,因为这会阻塞反应堆。

EM.run do
  io = File.open('path/to/file')
  read_chunk = proc do
    lines_sent = 10
    10.times do
      if line = io.gets
        send_to_db(line) do
          # when the DB call is done
          lines_sent -= 1
          EM.next_tick(read_chunk) if lines_sent == 0
        end
      else
        EM.stop
      end
    end
  end
  EM.next_tick(read_chunk)
end

请参阅What is the best way to read files in an EventMachine-based app?

答案 1 :(得分:1)

如果您还没有,可以查看EM::FileStreamer。首先,FileStreamer使用基于C ++的“快速文件阅读器”。你不能通过本地套接字/管道传输文件,并在一个单独的进程中处理发送到数据库,该进程正在另一端进行侦听吗?

还有一个基于非光纤的示例,在ThreadedResource中优雅地处理同步数据库连接,以防有用......特别提到了Cassandra。虽然听起来你的Cassandra库是基于光纤的。