6

eventmachine の非エコーサーバーの例を見つけるのに数日を費やしましたが、何もないようです。ファイルを受け入れて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 スタイル」で行う方法がわかりません。データをチャンクで読み取り、各チャンクを Em.next_tick ブロック内のディスクに書き込む必要がありますか?

助けてくれてありがとう アンドレアス

4

4 に答える 4

3

2つの答え:

怠惰な答え: ブロッキング書き込みを使用するだけです。EM は、1 つの巨大な文字列ではなく、データの個別のチャンクを既に渡しています。したがって、実装例は少しずれている可能性があります。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 が適切に処理してくれるからです。応答が必要な場合は、ワーカー スレッドの完了時にメインのリアクタ スレッドで実行されるコールバックを使用します。また、ここではIOブロッキングを扱っており、CPUの同時実行性を達成しようとしているのではないため、GILはこのケースでは問題になりません。

ただし、すべてを同じファイルに書き込むつもりだった場合は、遅延に注意する必要があります。これは、スレッドが同時に同じファイルに書き込もうとする可能性が高いため、同期の問題が発生するためです。

于 2012-11-01T07:31:19.610 に答える
1

docsから、ファイルを添付するだけでよいようです(ご指摘のとおり、それは有効ではないかもしれませんが、オプションは File.write/ie blocks を使用することです...)およびsend_data

ブロッキング/ノンブロッキングIOとEMを混在させることはできないと思っていましたが:(

ソース データがソケットであることを考えると、それは EventMachine によって処理されると思います。

おそらくGoogleグループへの質問...

~クリス

于 2011-01-10T11:47:27.527 に答える
1

残念ながら、ファイルは一部のインターフェースにうまく反応しません。IO#write よりも効率的なものが必要な場合 (これはほとんどありません)、EIOを使用できます。

EIO は実際にはリアクターのブロックを軽く解除するだけで、わずかなバッファリングを提供します。特定のレイテンシーが問題である場合、またはディスクが非常に遅い場合は、役立つ可能性があります。他のほとんどの場合、それはおそらくほとんど利点のない努力の集まりです。

于 2012-04-25T06:03:39.560 に答える
0

これは、EventMachine ベースのアプリでファイルを読み取る最良の方法は何ですか? とよく似ています。(しかし、ファイルを効率的に読み取る方法を知りたかったのです)。非ブロック ファイル API はないようです。そのため、できる最善の方法は、短いバーストを で書き込むnext_tickか、( で)書き込みを延期してdefer、別のスレッドで実行されるようにすることです (ただし、方法についてはわかりません)。そのソリューションのパフォーマンス)。

于 2011-01-11T07:28:11.613 に答える