resque & sidekiq
resque 一個 worker 通過 fork 方式來產生多個 worker 處理多個任務
fork 一個進程,操作系統會建立一個獨立分開的地址空間,並且從父進程複製所有的內存片段到這個地址裏面去。 這就意味着對於操作系統來說,對於 fork 的進程切換上下文,因爲需要保存和加載所有數據,所以代價更大。 而且如果父進程死掉了,這些 fork 的子進程沒有退出的話,將會變成殭屍進程。
sidekiq 一個 worker 使用的 Thread 方式產生多個線程 處理多個任務。
thread 多線程的話是共享地址空間,內存並且多線程之間的交互也比較方便。而且你也不用擔心殭屍進程的問題,一旦進程死掉, 所有的線程會自動被殺掉。但這種方式也有缺點,你必須保證代碼是線程安全的,不然可能會引起麻煩
resque 比 sidekiq 更消耗內存
resque 的 worker 不需要考慮線程安全問題,sidekiq 必須考慮
resque 實現
安裝Redis
安裝redis-namespace
安裝Resque
gem install redis redis-namespace resque、dalli
配置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 實現
安裝Redis
安裝redis-namespace
安裝Sidekiq
gem install redis redis-namespace sidekiq
配置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/