Ruby on Railsでのバックグラウンドビデオ処理

ユーザーがビデオをアップロードするWebサイトがあり、このビデオをflv形式に変換する必要があるとします。

ロード直後にこれを行うことは、現在のワークフローでは適切ではありません。 フローの数には制限があり、負荷が大きいとサイトは利用できなくなります。

デーモンがこれらのビデオファイルを処理する場合、はるかに良いでしょう。



デーモンのロジックは次のとおりです-デーモンはデータベースから未処理のオブジェクトを選択し(たとえば、状態フラグを使用して日付で並べ替え)、対応するビデオファイルを変換し、データベースのレコードを更新して、ステータスを「処理済み」(または「処理エラー」)に設定します。

独自のデーモンを作成するには、 デーモンライブラリを使用できます(奇妙なことに)。 デーモンは、2つの部分で構成されます。バックグラウンドプロセスを制御するスクリプトと、デーモンロジックを含むスクリプトです。 私たちの場合、これらはscript / video_converter_controlおよびlib / video_converterファイルになります。



スクリプト/ video_converter_control:

require 'rubygems'

require 'daemons'



options = {:app_name => "video_converter",

:ARGV => ARGV,

:dir_mode => :script,

:dir => '../tmp/pids',

:log_output => false,

:multiple => false,

:ontop => false,

:mode => :load,

:backtrace => false,

:monitor => false

# daemons ( monitor), monit

}



Daemons.run(File.join(File.dirname(__FILE__), '../lib/video_converter.rb'), options)









lib / video_converter:

require File.dirname(__FILE__) + '/../config/boot'

require RAILS_ROOT + "/config/environment"



SLEEP_TIME = 1



logger = RAILS_DEFAULT_LOGGER



loop do

video = Video.find(:first, :conditions => {:state => Video::PENDING_STATE}, :order => "id ASC")

success = video.process

if success.empty?

video.update_attribute(:state, Video::CONVERTED_STATE)

else

logger.info "VideoConverter: video #{video.id} converting failure"

video.update_attribute(:state, Video::FAILURE_STATE)

end

sleep(SLEEP_TIME)

end









次のようにデーモンを操作できます。

estarter@ny $ ./script/video_converter_control status

video_converter: no instances running

estarter@ny $ ./script/video_converter_control start

estarter@ny $ ./script/video_converter_control status

video_converter: running [pid 5957]

estarter@ny $ ./script/video_converter_control stop

estarter@ny $ ./script/video_converter_control status

video_converter: no instances running









ここで、コンバータの「電力」を増やします。 複数のビデオファイルを同時に処理することが可能であり、必要です。 最も簡単なオプションは複数のデーモンを実行することですが、これにより同期の問題が発生します。 複数のプロセスが同時に1つのファイルを処理するとは限りません。 これは、たとえば、対応するフラグ(Video :: PROCESSING_STATE)を設定してデータベース内のレコードを「ブロック」することで解決できます。

ただし、処理が1つのサーバーでのみ発生する場合は、よりスマートに実行できます。メインデーモンでスレッドを作成します。

これらの目的には、 spawnプラグインが適しています。これにより、ストリームを簡単に作成して操作できます。 これで、デーモンは一度に複数のオブジェクトを選択し、それらを別々のスレッドで処理します。



lib / video_converter:

require File.dirname(__FILE__) + '/../config/boot'

require RAILS_ROOT + "/config/environment"

include Spawn



THREAD_COUNT = 5 # ,

SLEEP_TIME = 1



logger = RAILS_DEFAULT_LOGGER

spawn_ids = []



loop do

videos = Video.find(:all, :conditions => {:state => Video::PENDING_STATE}, :order => "id ASC", :limit => THREAD_COUNT)

videos.each_with_index do |video, idx|

logger.info "VideoConverter: convert #{videos.size} videos"

spawn_ids[idx] = spawn do

success = video.process

if success.empty?

video.update_attribute(:state, Video::CONVERTED_STATE)

else

logger.info "VideoConverter: video #{video.id} converting failure"

video.update_attribute(:state, Video::FAILURE_STATE)

end

end

end

wait(spawn_ids)

sleep(SLEEP_TIME)

end









データアプローチは、多くのリソースを消費するタスクに使用できます。



オリジナルは私のブログにあります。




All Articles