Rubyの標準パッケージでJobQueueができます。処理を後回しにしたら早いとか、NoSQLとか、◯◯便利と言われるけど、私はdrubyを推したい。drubyはRubyの標準パッケージで、すぐ使えて便利。
drubyとスレッドを使う
druby(分散Ruby)は、マルチスレッド化にも対応した、よく出来た分散オブジェクト技術。
drubyを使えば、通常のオブジェクトをネットワークに公開できる。
今回は、Queueクラスとdrubyを作ったジョブ・キューサーバーを数行で作る。
Queue.server.rb
メインとなるサーバー、たったこれだけで、キューサーバーが作れる。
#!/usr/bin/env ruby -Ku #coding:utf-8 #サーバー require 'thread' require 'drb/drb' #起動 q = Queue.new DRb.start_service("druby://localhost:12345", q) DRb.thread.join
Client.push.rb
キューサーバーに、ジョブを突っ込むクラス
#!/usr/bin/env ruby -Ku #coding:utf-8 require 'thread' require 'drb/drb' q = DRbObject.new_with_uri("druby://localhost:12345") #サーバーに接続 #とりあえず、100ジョブ 100.times{|i| q.push "we add #{i}" }
Client.pop.rb
サーバーからジョブを取り出して仕事をする。
#!/usr/bin/env ruby -Ku #coding:utf-8 require 'thread' require 'drb/drb' q = DRbObject.new_with_uri("druby://localhost:12345") loop{|i| puts q.pop}#←ここがポイント(後述
ジョブサーバーのできあがり
これに、daemons.rb でデーモン化すれば、簡単に作ることができる。MongoDBやその他NoSQLに飛ばすより、とっても楽だし。そもそもSQLに書き出して永続化することすら面倒なので単純な文字列の受け渡し程度なら、十分仕事をしてくれる、
ポイントはここ
loop{|i| puts q.pop} #データが来るまで停止する
ここがポイント。q.pop はマルチスレッド化に対応しているので、popするべきQueueデータがなければ、そこで入力待ちになります。入力待ちで停止しますね。入力が来ない限り、loop{}を起動したrubyのmainスレッドはsleepしてお休み厨です。
入力側でpush しない限り停止するのでsleepを使わずに済みます。環境(CPU)に優しいループが作れます。
入力を待って仕事をするので、イベント・ドリブンにも近い感じすらある。