MQ 全稱爲 Message Queue, 消息隊列(MQ)是一種應用程序對應用程序的通信方法。應用程序通過讀寫出入隊列的消息(針對應用程序的數據)來通信,而無需專用連接來鏈接它們。
RabbitMQ 是一個在 AMQP 基礎上完整的,可複用的企業消息系統。他遵循 Mozilla Public License 開源協議。
RabbitMQ WIKI:https://zh.wikipedia.org/zh/RabbitMQ
RabbitMQ 百科:http://baike.baidu.com/view/4095865.htm
RabbitMQ 官網:http://www.rabbitmq.com/
RabbitMQ 官網下載:http://www.rabbitmq.com/download.html
RabbitMQ 官網安裝文檔:http://www.rabbitmq.com/install-rpm.html
RabbitMQ 文檔:
優先:http://www.rabbitmq.com/getstarted.html
次要:http://www.rabbitmq.com/documentation.html
安裝( 參考:https://ruby-china.org/topics/35230 | https://www.jianshu.com/p/30b6193785dc)
Gemfile
gem 'standby' # pgbouncer 數據庫讀寫分離
#悲觀鎖 "select * from where xxx for update"
#樂觀鎖 add_column :destinations, :lock_version, :integer 更多(http://hedengcheng.com/?p=771)
gem 'with_advisory_lock' #狀態鎖 行鎖(with_lock)
gem 'bunny' #client
gem 'sneakers' #service
client demo bunny_service.rb
class BunnyService
def initialize queue
@queue = queue
@amqp_url = $setting['amqp']['url']
end
def push message
begin
conn = Bunny.new(@amqp_url)
conn.start
ch = conn.create_channel
q = ch.queue(@queue, :durable=> true, :auto_delete => false)
q.publish(message.to_json)
conn.close
rescue => e
$logger.info("FATAL bunny push fail: #{e.message}")
end
end
#低於3.5.3的版本需要安裝插件 https://www.cloudamqp.com/docs/delayed-messages.html
def delay message, expire_time
begin
conn = Bunny.new(@amqp_url)
conn.start
ch = conn.create_channel
expire_time *= 1000
dlx_queue = "dlx_#{@queue}_#{expire_time}"
q = ch.queue(dlx_queue, arguments: {
'x-dead-letter-exchange' => '',
'x-dead-letter-routing-key' => @queue,
'x-message-ttl' => expire_time
})
q.publish(message.to_json, routing_key: dlx_queue)
conn.close
rescue => e
$logger.info("FATAL bunny delay fail: #{e.message}")
end
end
def delete
begin
conn = Bunny.new(@amqp_url)
conn.start
ch = conn.create_channel
ch.queue_delete(@queue)
rescue => e
$logger.info("FATAL bunny delete fail: #{e.message}")
end
end
end
service demo
config/initializers/sneaker.rb
require Rails.root.join('config', 'initializers', 'setting')
opts = {
daemonize: true,
amqp: $setting['amqp']['url'],
log: "log/sneakers.log",
pid_path: "tmp/pids/sneakers.pid",
threads: $setting['amqp']['threads'],
workers: $setting['amqp']['workers'],
timeout_job_after: 2.minutes, # Maximal seconds to wait for job
prefetch: 8, # Grab 10 jobs together. Better speed.
ack: true,
share_threads: true
}
Sneakers.configure(opts)
Sneakers.logger.level = Logger::INFO
workers/service_worker.rb
class ServiceWorker
include Sneakers::Worker
from_queue "worker.you_worker_name.queue"
def work msg
message = JSON.parse msg
begin
#doing message
rescue => e
e.message
end
ack!
end
end
start
bundle exec rake sneakers:run RAILS_ENV=production