resque VS sidekiq & AMQP - RabbitMQ 消息處理

resque & sidekiq

resque 一個 worker 通過 fork 方式來產生多個 worker 處理多個任務

fork 一個進程,操作系統會建立一個獨立分開的地址空間,並且從父進程複製所有的內存片段到這個地址裏面去。 這就意味着對於操作系統來說,對於 fork 的進程切換上下文,因爲需要保存和加載所有數據,所以代價更大。 而且如果父進程死掉了,這些 fork 的子進程沒有退出的話,將會變成殭屍進程。

sidekiq 一個 worker 使用的 Thread 方式產生多個線程 處理多個任務。

thread 多線程的話是共享地址空間,內存並且多線程之間的交互也比較方便。而且你也不用擔心殭屍進程的問題,一旦進程死掉, 所有的線程會自動被殺掉。但這種方式也有缺點,你必須保證代碼是線程安全的,不然可能會引起麻煩

resque 比 sidekiq 更消耗內存

resque 的 worker 不需要考慮線程安全問題,sidekiq 必須考慮

resque 實現
  1. 安裝Redis

  2. 安裝redis-namespace

  3. 安裝Resque

    gem install redis redis-namespace resque、dalli

  4. 配置resque信息

config/initializers/load_resque.rb

require 'resque'
Resque.redis = 'localhost:6379'
Resque.redis.namespace = "webtails:resque"
Resque.redis.expire "key", 100 #設置數據在redis中的有效期
Resque::Plugins::Status::Hash.expire_in = (24 * 60 * 60) # 24hrs in seconds

5.配置workers

require "resque/tasks"

task "resque:setup" => :environment

6.編寫Task類

class SendEmailTask
  @queue = "demo_task"

  def self.perform(target_email) 
    result = sendEmail(target_email) 
    Resque.redis[target_email] = result 
  end 
end

7.啓動

VVERBOSE=1 COUNT=5 QUEUE=demo_task rake environment resque:workers

PIDFILE=./tmp/pids/demo_task.pid BACKGROUND=yes QUEUE=demo_task rake resque:work >>  /srv/rorapps/demo/log/demo_task.log &

8.web routes.rb

mount Resque::Server, at: ‘/resque’

sidekiq 實現
  1. 安裝Redis

  2. 安裝redis-namespace

  3. 安裝Sidekiq

    gem install redis redis-namespace sidekiq

  4. 配置sidekiq信息

config/secrets.yml

redis: &redis
   redis_server: 'localhost'
   redis_port: 6379
   redis_db_num: 15
   redis_namespace: 'demo_sidekiq'
development:
  <<: *redis

config/initializers/load_sidekiq.rb

redis_server = Rails.application.secrets.redis_server
redis_port = Rails.application.secrets.redis_port
redis_db_num = Rails.application.secrets.redis_db_num
redis_namespace = Rails.application.secrets.redis_namespace

Sidekiq.configure_server do |config|
  p redis_server
  config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end

Sidekiq.configure_client do |config|
  config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
end

5.啓動配置文件 config/sidekiq.yml

bundle exec sidekiq –help

---
:concurrency: 5
:pidfile: ./tmp/pids/sidekiq.pid
development:
  :concurrency: 5
test:
  :concurrency: 5
production:
  :concurrency: 5
:queues:
  - default
  - cloud_watch
  - healthy
  - sync_order

6.配置workers

class CloudWatchWorker
  include Sidekiq::Worker
  sidekiq_options queue: :cloud_watch, retry: false, backtrace: true
  def perform(name, options = {}) 
    #do something
  end 
end

7.啓動Sidekiq

bundle exec sidekiq -C config/sidekiq.yml

or use capistrano

RBENV_ROOT=~/.rbenv RBENV_VERSION=2.1.2 ~/.rbenv/bin/rbenv exec bundle exec sidekiq –index 0 –pidfile /srv/rorapps/demo/shared/tmp/pids/sidekiq.pid –environment production –logfile /srv/rorapps/demo/shared/log/sidekiq.log –queue sms, notification –concurrency 10 –daemon

8.測試調用

CloudWatchWorker.perform_async ‘SuccessOrder’, {OrderRecord.last}

9.gem capistrano-sidekiq

bundle exec cap install

run cap -vT

set :sidekiq_config, “#{current_path}/config/sidekiq.yml”

關於capistrano http://www.rails365.net/articles/shi-yong-capistrano-bu-shu-rails-ying-yong

10.gem ‘sinatra’ 監控頁面

require ‘sidekiq/web’
mount Sidekiq::Web => ‘/sidekiq’

AMQP & RabbitMQ 還在摸索階段

AMQP 高級消息隊列協議是一個異步消息傳遞所使用的應用層協議規範

RabbitMQ 是AMQP的一種基於erlang的實現

http://www.infoq.com/cn/articles/AMQP-RabbitMQ
http://codemacro.com/2013/04/11/rabbitmq-erlang/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章