我花了好几天现在为eventmachine找到了一些非echo服务器示例,但似乎没有。假设我想编写一个接受文件并将其写入Tempfile的服务器:
require 'rubygems'
require 'tempfile'
require 'eventmachine'
module ExampleServer
def receive_data(data)
f = Tempfile.new('random')
f.write(data)
ensure
f.close
end
end
EventMachine::run {
EventMachine::start_server "127.0.0.1", 8081, ExampleServer
puts 'running example server on 8081'
}
写入文件会阻塞反应堆,但我不知道怎么做'Eventmachine style'。我是否必须以块的形式读取数据并将每个块写入Em.next_tick块中的磁盘?
感谢您的帮助 安德烈亚斯
答案 0 :(得分:3)
两个答案:
懒惰回答:只使用阻止写入。 EM已经在处理离散的数据块,而不是一个巨大的字符串。所以你的示例实现可能有点偏。您确定要为EM提供的每个块创建一个新的临时文件吗?但是,我将继续假设您的示例代码按预期工作。
不可否认,懒惰方法取决于您正在编写的设备,但尝试同时将几个大型流写入磁盘将成为一个主要瓶颈,您将失去基于事件的优势服务器无论如何。你最终会在整个地方寻找杂乱的磁盘,IO性能将会直线下降,服务器的性能也会下降。使用RAM可以同时处理很多事情,但是一旦你开始处理块设备和IO调度,无论你做什么,你都会遇到性能瓶颈。
但是,我猜你可能想要对磁盘执行一些长写操作,同时希望对其他非IO重请求进行低延迟响应。所以,也许是一个好的答案:
使用defer。
require 'rubygems'
require 'tempfile'
require 'eventmachine'
module ExampleServer
def receive_data(data)
operation = proc do
begin
f = Tempfile.new('random')
f.write(data)
ensure
f.close
end
end
callback = proc do
puts "I wrote a file!"
end
EM.defer(operation, callback)
end
end
EventMachine::run {
EventMachine::start_server "127.0.0.1", 8081, ExampleServer
puts 'running example server on 8081'
}
是的,这确实使用了线程。在这种情况下,它确实不是那么糟糕:你不必担心线程之间的同步,因为EM很适合为你处理这个问题。如果需要响应,请使用回调,该回调将在工作线程完成时在主反应器线程中执行。此外,对于这种情况,GIL是一个非问题,因为你在这里处理IO阻塞,而不是试图实现CPU并发。
但是如果你打算将所有内容写入同一个文件,那么你必须小心推迟,因为同步问题会出现,因为你的线程可能会同时尝试写入同一个文件。 / p>
答案 1 :(得分:1)
从docs开始,您似乎只需要attach该文件(虽然您指出,这可能无效,但似乎可以选择使用File.write / ie blocking ......)和send_data。
虽然我认为你不能将阻塞/非阻塞IO与EM混合:(
鉴于源数据是套接字,我想这将由EventMachine处理。
也许是google group ...
的问题〜克里斯
答案 2 :(得分:1)
不幸的是,文件对选择的接口反应不佳。如果你需要比IO#write更有效的东西(不太可能),那么你可以使用EIO。
EIO实际上只会轻轻解锁反应堆,并为您提供少量的缓冲。如果特定延迟是一个问题,或者您的磁盘确实很慢,那可能会有所帮助。在大多数其他情况下,它可能只是一堆努力而没什么好处。
答案 3 :(得分:0)
这与What is the best way to read files in an EventMachine-based app?非常相似(但我想知道如何有效地阅读文件)。似乎没有任何非阻塞文件API,因此您可以做的最好的事情是使用next_tick
编写短突发或推迟写入(使用defer
)以便它在单独运行线程(但我不知道该解决方案的性能如何)。