<form id="99h3p"></form>

      <em id="99h3p"></em>

                  <address id="99h3p"></address>
                  主頁 > 知識庫 > 網絡編程 > Ruby >

                  Rails 4.0 先睹為快:作業隊列

                  來源:oschina 作者:紅薯 發表于:2012-06-26 08:32  點擊:
                  Rails 最近增加了一個作業隊列系統,讓我們來看看如何使用。 Run, baby, run! 這個隊列 API 非常簡單,你將對象放到隊列中,而這個對象需要提供一個名為 run 的方法,下面是個簡單例子: 1 class TestJob 2 def run 3 puts I am running! 4 end 5 end 6 7 Rai
                  Rails 最近增加了一個作業隊列系統,讓我們來看看如何使用。

                  Run, baby, run!

                  這個隊列 API 非常簡單,你將對象放到隊列中,而這個對象需要提供一個名為 run 的方法,下面是個簡單例子:
                  1 class TestJob
                   
                  2   def run
                   
                  3     puts "I am running!"
                   
                  4   end
                   
                  5 end
                   
                  6  
                   
                  7 Rails.queue.push(TestJob.new)
                   
                  8 => "I am running!"
                   
                  對大多數人來說,這已足夠。隊列是在一個獨立的線程中運行,因此你的應用不會因為一些很復雜的作業而導致無響應
                  Rails 中的基本隊列并不是一個長期的解決方案,其目的僅僅是提供一個通用的 API 可以用來支持更可靠的隊列系統。例如當你需要從 Resque 切換到 Sidekiq,你不需要更改你應用代碼,你只需關心對象進入隊列以及編組。
                  你也可以編寫自己的隊列,下面是一個簡單的隊列實現:
                  1 class MyQueue
                   
                  2   def push(job)
                   
                  3     job.run
                   
                  4   end
                   
                  5 end
                   
                  要使用你自定義的隊列,只需要在 application.rb 中設置:
                  1 config.queue = MyQueue
                   
                  上面例子來源于 Rails 的測試套件,它定義了一個非異步的隊列,當作業被放到隊列中便立即執行。下面讓我們開發一個實際的作業,無需依賴于 Queue 類。
                  01 class MyQueue
                   
                  02   def initialize
                   
                  03     @queue = []
                   
                  04   end
                   
                  05  
                   
                  06   def push(job)
                   
                  07     @queue.push(job)
                   
                  08   end
                   
                  09  
                   
                  10   def pop
                   
                  11     @queue.pop
                   
                  12   end
                   
                  13 end
                   
                  這個例子我們實現了一個簡單的隊列,接下來你需要告訴 Rails 的 QueueConsumer 來使用這個隊列,可以在 application.rb 的 initializer 塊中設置:
                  1 intializer 'start queue consumer' do |app|
                   
                  2   qpp.queue_consumer = config.queue_consumer.start(app.queue)
                   
                  3   at_exit { app.queue.consumer.shutdown }
                   
                  4 end
                   
                  然后我們將新的作業放到隊列中:
                  1 Rails.queue.push(TestJob.new)
                   
                  啥也沒有,為什么?檢查 QueueConsumer:
                  1 Rails.application.queue_consumer
                   
                  2 => #<Rails::Queueing::ThreadedConsumer @queue=#<MyQueue @queue=[]>, @thread=#<Thread dead>>
                   
                  然后你會發現線程死了,我們可以強行要求隊列處理:
                  1 Rails.application.queue_consumer.start
                   
                  2 => "I am running!"
                   
                  回過頭來看看到底發生了什么。首先我們找到 ThreadedConsumer#start
                  01 def start
                   
                  02   @thread = Thread.new do
                   
                  03     while job = @queue.pop
                   
                  04       begin
                   
                  05         job.run
                   
                  06       rescue Exception => e
                   
                  07         handle_exception e
                   
                  08       end
                   
                  09     end
                   
                  10   end
                   
                  11   self
                   
                  12 end
                   
                  這個線程只有在 @queue.pop 返回一個 true 值的時候才會運行,這不太合理,我們需要不斷的將對象推到隊列中,讓我們來看看 Queue#pop 發生了什么:
                  01 # Retrieves data from the queue.  If the queue is empty, the calling thread is
                   
                  02 # suspended until data is pushed onto the queue.  If +non_block+ is true, the
                   
                  03 # thread isn't suspended, and an exception is raised.
                   
                  04 #
                   
                  05 def pop(non_block=false)
                   
                  06   while true
                   
                  07     @mutex.synchronize do
                   
                  08       @waiting.delete(Thread.current)
                   
                  09       if @que.empty?
                   
                  10         raise ThreadError, "queue empty" if non_block
                   
                  11         @waiting.push Thread.current
                   
                  12         @resource.wait(@mutex)
                   
                  13       else
                   
                  14         retval = @que.shift
                   
                  15         @resource.signal
                   
                  16         return retval
                   
                  17       end
                   
                  18     end
                   
                  19   end
                   
                  20 end
                   
                  終于有點明白了,Queue#pop 是一個無限的循環在等待其需要的內容。而我們簡單的 MyQueue 類在 ThreadConsumer#start 調用的時候會返回 nil,因此隊列里沒對象,線程就結束了。甚至當我們往隊列里放對象時,再次 pop 操作后也會結束。
                  簡單起見,只需要讓 MyQueue 繼承 Queue 即可:
                  1 class MyQueue < Queue
                   
                  2 end
                   
                  現在我們可以:
                  1 Rails.queue.push(TestJob.new)
                   
                  2 => "I am running!"
                   
                  Rails 4.0 中的隊列系統是一個非常簡單的解決方案,我們期待正式版的發布,能夠支持更多更好的后臺作業處理庫。
                  需要注意的是,目前的隊列還是 beta 版本,API 可能還有有所更改。
                  英文原文,OSCHINA原創翻譯

                    有幫助
                    (0)
                    0%
                    沒幫助
                    (1)
                    100%
                    自在自线亚洲А∨天堂在线,亚洲熟妇中文字幕五十中出,亚洲熟妇AV一区