Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up
for free
Messages queues don't need to be scary.
Glen Mailer
October 14, 2013
Technology
1
84
Messages queues don't need to be scary.
An introduction tutorial to AMQP with RabbitMQ and Ruby.
Glen Mailer
October 14, 2013
Tweet
Share
More Decks by Glen Mailer
See All by Glen Mailer
glenjamin
0
39
glenjamin
1
290
glenjamin
0
140
glenjamin
1
100
glenjamin
1
820
Other Decks in Technology
See All in Technology
ymatsuwitter
0
240
soracom
0
230
recruitengineers
0
250
shirayanagiryuji
1
180
waka
5
2.6k
kadoppe
1
230
tsuyo
0
730
kaga
0
300
kentaro
2
510
kawaguti
0
430
yoku0825
PRO
2
670
charity
12
13k
Featured
See All Featured
tenderlove
54
3.5k
sachag
267
17k
sugarenia
233
880k
reverentgeek
27
2.1k
searls
204
37k
mthomps
38
2.3k
reverentgeek
167
7.3k
pedronauck
652
110k
maggiecrowley
10
540
hannesfritz
29
980
paulrobertlloyd
73
1.5k
denniskardys
220
120k
Transcript
Message queues don't need to be scary An intro workshop
to AMQP
AMQP
Advanced Message Queuing Protocol
None
Why?
Job Queue Event Stream Buffered RPC
Job Queue
Producer Consumer
Producer Consumer Producer
Producer Consumer Producer Consumer
Producer Consumer Producer Consumer
Slow Operations Expensive Operations Brittle Operations
Producer c = create_channel q = c.queue("task") x = c.default_exchange
x.publish( "task", "payload" ) Consumer c = create_channel q = c.queue("task") q.subscribe(worker) worker = fn(*message) { // do stuff }
Acknowledging Messages q = c.queue("task") q.subscribe(worker, ack = TRUE) worker
= fn(info, metadata, body) { // do work c.acknowledge(info.delivery_tag) }
Publishing Options Mandatory Will error if not queued Immediate Will
error if no consumer available Confirm Server acknowledges receipt
Queue Declare Options Passive Don't create, get reference to existing
queue Durable Queue still exists after a broker restart
Event Stream
Producer Consumer Producer Consumer Consumer Consumer Producer
Topic Exchange routing.key Exact match routing.*.key routing.#.key Wildcard matching routing.key
routing.a.key routing.b.key routing.a.b.key
(soft) Real-time updates User notifications Work distribution
Binding a Queue x = c.exchange("activity”) q = c.queue("alert") q.bind(x,
"balance.*") q.bind(x, "transfer.out") x.publish("balance.low") x.publish("transfer.in") x.publish("transfer.out")
Queue Declare Options Exclusive Only one consumer on this queue
at any time Auto Delete Queue is deleted after consumer disconnects
Simulator Demo
Buffered RPC
Producer Consumer
Message Header Reply To Correlation ID
Reply To reply = c.queue("abcdef") x.publish("request", :headers => { :replyTo
=> "abcdef" }) reply.subscribe(handleResponse)
Correlation ID x.publish("request1", :headers => { :replyTo => "abcdef", :correlationID
=> "request1" }) x.publish("request2", :headers => { :replyTo => "abcdef", :correlationID => "request2" })
Smooth out Spikes Transparently scale Deferred Response
Why not just use … ?
Delayed Job Resque / Sidekiq Beanstalkd
JMS Stomp MQTT
ØMQ
Ruby Quickstart
gem install bunny
require 'bunny' url = 'amqp://un:pw@host:5672/vhost' conn = Bunny.new(url) conn.start
ch = conn.create_channel ch.prefetch 1
declare_options = {:no_declare => true} q = ch.queue(name, options)
options = {:block => true, :ack => true} q.subscribe(options) do |info, meta, body| # do stuff ch.ack(info.delivery_tag) end
declare_options = {:no_declare => true} x = ch.topic("name", declare_options)
x.publish("message", :routing_key => "key")