Slide 1

Slide 1 text

Message queues don't need to be scary An intro workshop to AMQP

Slide 2

Slide 2 text

AMQP

Slide 3

Slide 3 text

Advanced Message
 Queuing Protocol

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Why?

Slide 6

Slide 6 text

Job Queue
 Event Stream
 Buffered RPC

Slide 7

Slide 7 text

Job Queue

Slide 8

Slide 8 text

Producer Consumer

Slide 9

Slide 9 text

Producer Consumer Producer

Slide 10

Slide 10 text

Producer Consumer Producer Consumer

Slide 11

Slide 11 text

Producer Consumer Producer Consumer

Slide 12

Slide 12 text

Slow Operations
 Expensive Operations
 Brittle Operations

Slide 13

Slide 13 text

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 }

Slide 14

Slide 14 text

Acknowledging Messages q = c.queue("task") q.subscribe(worker, ack = TRUE) worker = fn(info, metadata, body) { // do work c.acknowledge(info.delivery_tag) }

Slide 15

Slide 15 text

Publishing Options Mandatory Will error if not queued Immediate Will error if no consumer available Confirm Server acknowledges receipt

Slide 16

Slide 16 text

Queue Declare Options Passive Don't create, get reference to existing queue Durable Queue still exists after a broker restart

Slide 17

Slide 17 text

Event Stream

Slide 18

Slide 18 text

Producer Consumer Producer Consumer Consumer Consumer Producer

Slide 19

Slide 19 text

Topic Exchange routing.key Exact match routing.*.key routing.#.key Wildcard matching routing.key routing.a.key routing.b.key routing.a.b.key

Slide 20

Slide 20 text

(soft) Real-time updates
 User notifications
 Work distribution

Slide 21

Slide 21 text

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")

Slide 22

Slide 22 text

Queue Declare Options Exclusive Only one consumer on this queue at any time Auto Delete Queue is deleted after consumer disconnects

Slide 23

Slide 23 text

Simulator Demo

Slide 24

Slide 24 text

Buffered RPC

Slide 25

Slide 25 text

Producer Consumer

Slide 26

Slide 26 text

Message Header
 Reply To
 Correlation ID

Slide 27

Slide 27 text

Reply To reply = c.queue("abcdef") x.publish("request", :headers => { :replyTo => "abcdef" }) reply.subscribe(handleResponse)

Slide 28

Slide 28 text

Correlation ID x.publish("request1", :headers => { :replyTo => "abcdef", :correlationID => "request1" }) x.publish("request2", :headers => { :replyTo => "abcdef", :correlationID => "request2" })

Slide 29

Slide 29 text

Smooth out Spikes
 Transparently scale
 Deferred Response

Slide 30

Slide 30 text

Why not just use … ?

Slide 31

Slide 31 text

Delayed Job
 Resque / Sidekiq
 Beanstalkd

Slide 32

Slide 32 text

JMS
 Stomp
 MQTT

Slide 33

Slide 33 text

ØMQ

Slide 34

Slide 34 text

Ruby Quickstart

Slide 35

Slide 35 text

gem install bunny

Slide 36

Slide 36 text

require 'bunny'
 
 url = 'amqp://un:pw@host:5672/vhost'
 conn = Bunny.new(url)
 conn.start
 ch = conn.create_channel
 ch.prefetch 1

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

declare_options = {:no_declare => true}
 x = ch.topic("name", declare_options)
 
 x.publish("message", :routing_key => "key")