SlideShare a Scribd company logo
1 of 65
Message Queueing
  from an MQ noob's perspective
Preamble

• I work for a global telco
• We push telco events and messages around
• All should be processed quickly and reliably
• Some generate a response
Scenario


• We send messages around in small text
  files, sometimes with RFC 2822 headers
• Use the UNIX sendf/recfiled mechanism
Problem


• It's entirely intolerant to faults
• ... and network latency
Our Solution


• Add in our own "message queueing"
• ... and some facilities to decouple delays
Shortcomings

• Messages cannot be sent to multiple hosts
• Target hosts are not easily reconfigurable
• It's developed in-house and has issues
Scenario

• multiple producers
• a consumer and its backup
• Systems separated by 100-400ms WAN
 • with occasional 100% packet loss
The Contenders
pymq

• very hazy on the details
• depends on MySQL? and Django?!?
• ignored while looking at kombu / rabbitmq
ZeroMQ aka 0MQ


"ZeroMQ is a message orientated IPC Library."
              - commenter on stackoverflow
AMQP
• Is a standard for message queueing
• Producers submit messages to brokers
• Brokers consist of exchanges and queues
• Exchanges route the messages
• Queues store messages
• Consumers pull messages out
RabbitMQ
RabbitMQ
Producer




              Broker




                       Consumer
RabbitMQ
Producer




                      Broker


           Exchange


                               Queue




                                       Consumer
RabbitMQ


Queues
RabbitMQ


Exchanges
RabbitMQ
RabbitMQ


Exchanges
RabbitMQ


 Routing
RabbitMQ


Exchange Types
RabbitMQ


Direct Exchanges
RabbitMQ


Topic Exchanges
RabbitMQ


Fanout Exchanges
RabbitMQ


Persistence
RabbitMQ


Broker Persistence
RabbitMQ


Message Persistence
RabbitMQ


1. Mark the exchange “durable”.
2. Mark the queue “durable”.
3. Set the message’s “delivery mode” to a value of 2
RabbitMQ


Persistence Warnings
RabbitMQ


Acknowledging
My Desired Setup

   Remote Host                      Processing Server

         Publisher                          Queue
                              ebs
                     Interw

          Queue                           Consumer
My Desired Setup

   Remote Host                     Processing Server

        Publisher                          Queue

                             ebs
                    Interw
          Queue                          Consumer



        Consumer
My Desired Setup

   Remote Host                   Processing Server

        Publisher                      Consumer
                           ebs
                    Interw

          Queue
Shovel

Remote Host                      Processing Server

     Publisher                           Queue


                            bs
       Queue          rwe              Consumer
                 Inte


      Shovel
=ERROR REPORT==== 7-Aug-2012::16:50:32 ===
** Generic server <0.366.0> terminating
** Last message in was {'$gen_cast',init}
** When Server state == {state,undefined,undefined,undefined,undefined,
                  hello_shovel,
                  {shovel,
                   {endpoint,
                    [{amqp_params_direct,<<"guest">>,<<"/">>,
                      rabbit@localhost,none,[]}],
                    []},
                   {endpoint,
                    [{amqp_params_network,<<"guest">>,<<"guest">>,
                      <<>>,"hardrock",undefined,0,0,0,infinity,none,
                      [#Fun<amqp_auth_mechanisms.plain.3>,
                       #Fun<amqp_auth_mechanisms.amqplain.3>],
                      [],[]}],
                    []},
                   0,on_confirm,#Fun<rabbit_shovel_sup.16.91344538>,
                   #Fun<rabbit_shovel_sup.16.91344538>,<<"hello">>,5},
                  undefined,undefined,undefined,undefined,undefined}
** Reason for termination ==
** {{badmatch,{error,access_refused}},
   [{rabbit_shovel_worker,make_conn_and_chan,1,[]},
    {rabbit_shovel_worker,handle_cast,2,[]},
    {gen_server2,handle_msg,2,[]},
    {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,227}]}]}
error in config file "/usr/local/etc/rabbitmq/rabbitmq.config" (37): syntax error
before: '.'
Shovel
[
     {rabbitmq_shovel, [
        {shovels, [
           {hello_shovel, [
               {sources, [
                  {brokers, ["amqp://"]}
               ]}
             , {destinations, [
                  {brokers, ["amqp://server"]}
               ]}
             , {queue, <<"hello">>}
           ]}
        ]}
     ]}
].
[
                       Shovel
     {rabbitmq_shovel, [
        {shovels, [
           {hello_shovel, [
               {sources, [
                   {brokers, ["amqp://"]}
                 , {declarations, [
                       {'exchange.declare', [
                           {exchange, <<"foo">>}
                         , {type, <<"direct">>}
                         , durable
                       ]}
                     , {'queue.declare', [
                         {queue, <<"hello">>}
                       ]}
                     , {'queue.bind', [
                         {exchange, <<"foo">>}
                       , {queue, <<"hello">>}
                       ]}
                   ]}
               ]}
             , {destinations, [
                   {brokers, ["amqp://hardrock"]}
               ]}
             , {queue, <<"hello">>}
           ]}
        ]}
     ]}
].
Installation
• 1. install RabbitMQ
 • (install homebrew; brew install rabbitmq;
     rabbitmq-server [-detached])
  • (yum install rabbitmq-server.noarch)
  • rabbitmqctl or http://server:55672/
• 2. pip install kombu, or pika, or puka, or ...
pika


"a pure-Python implementation of the
       AMQP 0-9-1 protocol"
Publisher
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('server'))
channel = connection.channel()
channel.queue_declare(queue='hello', durable=True)
channel.basic_publish(exchange='', routing_key='hello', body='Hello World!',
    properties=pika.BasicProperties(delivery_mode=2))
print " [x] Sent 'Hello World!'"
connection.close()




                            Publisher       Queue
Consumer
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))

channel = connection.channel()
channel.queue_declare(queue='hello', durable=True)

print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print ' [x] Received %r' % (body,)

channel.basic_consume(callback, queue='hello', no_ack=True)

channel.start_consuming()

                            Queue             Consumer
Remote Consumer   Local Publisher
Remote queues
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('server'))

channel = connection.channel()
channel.queue_declare(queue='hello', durable=True)

print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print ' [x] Received %r' % (body,)

channel.basic_consume(callback, queue='hello', no_ack=True)

channel.start_consuming()

                    Host 1               Host 2

                             Publisher             Queue



                             Consumer             Consumer
Remote Consumer   Local Consumer   Local Publisher
Acknowledgement
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('server'))

channel = connection.channel()
channel.queue_declare(queue='hello', durable=True)

print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print ' [x] Received %r' % (body,)
    raw_input('Press enter to ACK')
    ch.basic_ack(delivery_tag=method.delivery_tag)

channel.basic_consume(callback, queue='hello', no_ack=False)

channel.start_consuming()
Consumer   Publisher
Issues

• pika's BlockingConnection (my use case is
  simple enough) hard-codes the socket
  timeout and fails to cope with latency >1s
• Fails to cope at all with packet loss
Deleting a Queue

import pika
connection = pika.BlockingConnection(pika.ConnectionParameters('server'))
channel = connection.channel()
channel.queue_delete(queue='hello')
channel.close()
connection.close()
Kombu


"a messaging framework for Python"
Publisher

from kombu import BrokerConnection

with BrokerConnection('amqp://localhost') as conn:
    with conn.SimpleQueue('hello') as queue:
        queue.put('Hello World!')
        print " [x] Sent 'Hello World!'"
Bizarro errors


amqplib.client_0_8.exceptions.AMQPChannelException: (406,
u"PRECONDITION_FAILED - parameters for queue 'hello' in vhost '/'
not equivalent", (50, 10), 'Channel.queue_declare')
Publisher

from kombu import BrokerConnection

with BrokerConnection('amqp://localhost//') as conn:
    with conn.SimpleQueue('hello', queue_opts=dict(durable=False)) as queue:
        queue.put('Hello World!')
        print " [x] Sent 'Hello World!'"
Puka


"An opinionated RabbitMQ client"
Publisher

import puka

client = puka.Client('amqp://localhost//')
client.wait(client.connect())

client.wait(client.queue_declare(queue='hello', durable=True))

promise = client.basic_publish(exchange='', routing_key='hello',
    body='Hello World!')
client.wait(promise)
print " [x] Sent 'Hello World!'"

client.wait(client.close())
Other Plugins

• Management (web interface, quite nice)
• Federation (Shovel, but with MOAR)
• STOMP protocol support
STOMP


Simple (or Streaming) Text Orientated
         Messaging Protocol
STOMP


 "simple"
STOMP

{rabbitmq_stomp, [
    {tcp_listeners, [
        {"127.0.0.1", 61613}
      , {"::1",    61613}
    ]}
  , {default_user, [
        {login, "guest"}
      , {passcode, "guest"}
    ]}
]}
stompclient

from stompclient import PublishClient

client = PublishClient('localhost', 61613)
client.connect()
client.send('/queue/hello', 'Hello, world!')
client.disconnect()
stompclient
from kombu import BrokerConnection

with BrokerConnection('amqp://localhost') as conn:
    with conn.SimpleQueue('hello') as queue:
        queue.put('Hello World!')
        print " [x] Sent 'Hello World!'"




   from stompclient import PublishClient

   client = PublishClient('localhost', 61613)
   client.connect()
   client.send('/queue/hello', 'Hello, world!')
   client.disconnect()
stompclient
  from stompclient import PublishClient

  client = PublishClient('localhost', 61613)
  client.connect()
  client.send('/queue/hello', 'Hello, world!')
  client.disconnect()




from stompclient import PublishClient

with PublishClient('localhost', 61613) as client:
    client.send('/queue/hello', 'Hello, world!')
Celery


"a synchronous or asynchronous task queue/job
 queue based on distributed message passing"
TcpCatcher
• TCP, SOCKS, HTTP(S) proxy & monitor
• Can introduce latency and transmission
  errors
• Understands HTTP and images
• Can debug/interfere/log SSL traffic
• Free: www.tcpcatcher.fr

More Related Content

What's hot

服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScriptQiangning Hong
 
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksHow to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksCarlos Sanchez
 
VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareCosimo Streppone
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncioJames Saryerwinnie
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises Marc Morera
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015Fernando Hamasaki de Amorim
 
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Tom Croucher
 
How we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaHow we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaCosimo Streppone
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Brian Sam-Bodden
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsFabio Akita
 
Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendKirill Chebunin
 
Acus08 Advanced Load Balancing Apache2.2
Acus08 Advanced Load Balancing Apache2.2Acus08 Advanced Load Balancing Apache2.2
Acus08 Advanced Load Balancing Apache2.2Jim Jagielski
 
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)DECK36
 
Exploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your pluginsExploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your pluginsMarian Marinov
 
Dissecting the rabbit: RabbitMQ Internal Architecture
Dissecting the rabbit: RabbitMQ Internal ArchitectureDissecting the rabbit: RabbitMQ Internal Architecture
Dissecting the rabbit: RabbitMQ Internal ArchitectureAlvaro Videla
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Masahiro Nagano
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Ontico
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby CoreHiroshi SHIBATA
 

What's hot (19)

服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript服务框架: Thrift & PasteScript
服务框架: Thrift & PasteScript
 
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero ClicksHow to Develop Puppet Modules: From Source to the Forge With Zero Clicks
How to Develop Puppet Modules: From Source to the Forge With Zero Clicks
 
VUG5: Varnish at Opera Software
VUG5: Varnish at Opera SoftwareVUG5: Varnish at Opera Software
VUG5: Varnish at Opera Software
 
Writing Redis in Python with asyncio
Writing Redis in Python with asyncioWriting Redis in Python with asyncio
Writing Redis in Python with asyncio
 
When symfony met promises
When symfony met promises When symfony met promises
When symfony met promises
 
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
The worst Ruby codes I’ve seen in my life - RubyKaigi 2015
 
Apache con 2011 gd
Apache con 2011 gdApache con 2011 gd
Apache con 2011 gd
 
Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012 Streams are Awesome - (Node.js) TimesOpen Sep 2012
Streams are Awesome - (Node.js) TimesOpen Sep 2012
 
How we use and deploy Varnish at Opera
How we use and deploy Varnish at OperaHow we use and deploy Varnish at Opera
How we use and deploy Varnish at Opera
 
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
Server-Side Push: Comet, Web Sockets come of age (OSCON 2013)
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability Options
 
Symfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friendSymfony2 Service Container: Inject me, my friend
Symfony2 Service Container: Inject me, my friend
 
Acus08 Advanced Load Balancing Apache2.2
Acus08 Advanced Load Balancing Apache2.2Acus08 Advanced Load Balancing Apache2.2
Acus08 Advanced Load Balancing Apache2.2
 
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)
Our Puppet Story – Patterns and Learnings (sage@guug, March 2014)
 
Exploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your pluginsExploiting the newer perl to improve your plugins
Exploiting the newer perl to improve your plugins
 
Dissecting the rabbit: RabbitMQ Internal Architecture
Dissecting the rabbit: RabbitMQ Internal ArchitectureDissecting the rabbit: RabbitMQ Internal Architecture
Dissecting the rabbit: RabbitMQ Internal Architecture
 
Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015Rhebok, High Performance Rack Handler / Rubykaigi 2015
Rhebok, High Performance Rack Handler / Rubykaigi 2015
 
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
Построение распределенной системы сбора данных с помощью RabbitMQ, Alvaro Vid...
 
Practical Testing of Ruby Core
Practical Testing of Ruby CorePractical Testing of Ruby Core
Practical Testing of Ruby Core
 

Similar to Message Queueing - by an MQ noob

Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011David Troy
 
Introduction to Marionette Collective
Introduction to Marionette CollectiveIntroduction to Marionette Collective
Introduction to Marionette CollectivePuppet
 
Scaling application with RabbitMQ
Scaling application with RabbitMQScaling application with RabbitMQ
Scaling application with RabbitMQNahidul Kibria
 
MessagePack Rakuten Technology Conference 2010
MessagePack Rakuten Technology Conference 2010MessagePack Rakuten Technology Conference 2010
MessagePack Rakuten Technology Conference 2010Sadayuki Furuhashi
 
Scaling applications with RabbitMQ at SunshinePHP
Scaling applications with RabbitMQ   at SunshinePHPScaling applications with RabbitMQ   at SunshinePHP
Scaling applications with RabbitMQ at SunshinePHPAlvaro Videla
 
Lindsay distributed geventzmq
Lindsay distributed geventzmqLindsay distributed geventzmq
Lindsay distributed geventzmqRobin Xiao
 
Service Delivery Assembly Line with Vagrant, Packer, and Ansible
Service Delivery Assembly Line with Vagrant, Packer, and AnsibleService Delivery Assembly Line with Vagrant, Packer, and Ansible
Service Delivery Assembly Line with Vagrant, Packer, and AnsibleIsaac Christoffersen
 
Going real time with Socket.io
Going real time with Socket.ioGoing real time with Socket.io
Going real time with Socket.ioArnout Kazemier
 
LCA2014 - Introduction to Go
LCA2014 - Introduction to GoLCA2014 - Introduction to Go
LCA2014 - Introduction to Godreamwidth
 
Getting Started with Couchbase Ruby
Getting Started with Couchbase RubyGetting Started with Couchbase Ruby
Getting Started with Couchbase RubySergey Avseyev
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)James Titcumb
 
Service discovery like a pro (presented at reversimX)
Service discovery like a pro (presented at reversimX)Service discovery like a pro (presented at reversimX)
Service discovery like a pro (presented at reversimX)Eran Harel
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akkanartamonov
 
DRb and Rinda
DRb and RindaDRb and Rinda
DRb and RindaMark
 

Similar to Message Queueing - by an MQ noob (20)

RabbitMQ in Sprayer
RabbitMQ in SprayerRabbitMQ in Sprayer
RabbitMQ in Sprayer
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011Servers with Event Machine - David Troy - RailsConf 2011
Servers with Event Machine - David Troy - RailsConf 2011
 
Pycon - Python for ethical hackers
Pycon - Python for ethical hackers Pycon - Python for ethical hackers
Pycon - Python for ethical hackers
 
Introduction to Marionette Collective
Introduction to Marionette CollectiveIntroduction to Marionette Collective
Introduction to Marionette Collective
 
Scaling application with RabbitMQ
Scaling application with RabbitMQScaling application with RabbitMQ
Scaling application with RabbitMQ
 
web3j Overview
web3j Overviewweb3j Overview
web3j Overview
 
MessagePack Rakuten Technology Conference 2010
MessagePack Rakuten Technology Conference 2010MessagePack Rakuten Technology Conference 2010
MessagePack Rakuten Technology Conference 2010
 
Scaling applications with RabbitMQ at SunshinePHP
Scaling applications with RabbitMQ   at SunshinePHPScaling applications with RabbitMQ   at SunshinePHP
Scaling applications with RabbitMQ at SunshinePHP
 
Lindsay distributed geventzmq
Lindsay distributed geventzmqLindsay distributed geventzmq
Lindsay distributed geventzmq
 
Service Delivery Assembly Line with Vagrant, Packer, and Ansible
Service Delivery Assembly Line with Vagrant, Packer, and AnsibleService Delivery Assembly Line with Vagrant, Packer, and Ansible
Service Delivery Assembly Line with Vagrant, Packer, and Ansible
 
RabbitMQ for Perl mongers
RabbitMQ for Perl mongersRabbitMQ for Perl mongers
RabbitMQ for Perl mongers
 
Going real time with Socket.io
Going real time with Socket.ioGoing real time with Socket.io
Going real time with Socket.io
 
LCA2014 - Introduction to Go
LCA2014 - Introduction to GoLCA2014 - Introduction to Go
LCA2014 - Introduction to Go
 
Getting Started with Couchbase Ruby
Getting Started with Couchbase RubyGetting Started with Couchbase Ruby
Getting Started with Couchbase Ruby
 
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
Adding 1.21 Gigawatts to Applications with RabbitMQ (PHPNW Dec 2014 Meetup)
 
Service discovery like a pro (presented at reversimX)
Service discovery like a pro (presented at reversimX)Service discovery like a pro (presented at reversimX)
Service discovery like a pro (presented at reversimX)
 
R-House (LSRC)
R-House (LSRC)R-House (LSRC)
R-House (LSRC)
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akka
 
DRb and Rinda
DRb and RindaDRb and Rinda
DRb and Rinda
 

More from Richard Jones

Introduction to Game Programming
Introduction to Game ProgrammingIntroduction to Game Programming
Introduction to Game ProgrammingRichard Jones
 
Web micro-framework BATTLE!
Web micro-framework BATTLE!Web micro-framework BATTLE!
Web micro-framework BATTLE!Richard Jones
 
Intro to Game Programming
Intro to Game ProgrammingIntro to Game Programming
Intro to Game ProgrammingRichard Jones
 
Introduction to Game Programming Tutorial
Introduction to Game Programming TutorialIntroduction to Game Programming Tutorial
Introduction to Game Programming TutorialRichard Jones
 
State of Python (2010)
State of Python (2010)State of Python (2010)
State of Python (2010)Richard Jones
 
What's New In Python 2.6
What's New In Python 2.6What's New In Python 2.6
What's New In Python 2.6Richard Jones
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5Richard Jones
 
What's New In Python 2.4
What's New In Python 2.4What's New In Python 2.4
What's New In Python 2.4Richard Jones
 
Tkinter Does Not Suck
Tkinter Does Not SuckTkinter Does Not Suck
Tkinter Does Not SuckRichard Jones
 

More from Richard Jones (11)

Angboard
AngboardAngboard
Angboard
 
Don't do this
Don't do thisDon't do this
Don't do this
 
Introduction to Game Programming
Introduction to Game ProgrammingIntroduction to Game Programming
Introduction to Game Programming
 
Web micro-framework BATTLE!
Web micro-framework BATTLE!Web micro-framework BATTLE!
Web micro-framework BATTLE!
 
Intro to Game Programming
Intro to Game ProgrammingIntro to Game Programming
Intro to Game Programming
 
Introduction to Game Programming Tutorial
Introduction to Game Programming TutorialIntroduction to Game Programming Tutorial
Introduction to Game Programming Tutorial
 
State of Python (2010)
State of Python (2010)State of Python (2010)
State of Python (2010)
 
What's New In Python 2.6
What's New In Python 2.6What's New In Python 2.6
What's New In Python 2.6
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5
 
What's New In Python 2.4
What's New In Python 2.4What's New In Python 2.4
What's New In Python 2.4
 
Tkinter Does Not Suck
Tkinter Does Not SuckTkinter Does Not Suck
Tkinter Does Not Suck
 

Recently uploaded

Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyAlfredo García Lavilla
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 

Recently uploaded (20)

Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Commit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easyCommit 2024 - Secret Management made easy
Commit 2024 - Secret Management made easy
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 

Message Queueing - by an MQ noob

  • 1. Message Queueing from an MQ noob's perspective
  • 2. Preamble • I work for a global telco • We push telco events and messages around • All should be processed quickly and reliably • Some generate a response
  • 3. Scenario • We send messages around in small text files, sometimes with RFC 2822 headers • Use the UNIX sendf/recfiled mechanism
  • 4.
  • 5. Problem • It's entirely intolerant to faults • ... and network latency
  • 6. Our Solution • Add in our own "message queueing" • ... and some facilities to decouple delays
  • 7. Shortcomings • Messages cannot be sent to multiple hosts • Target hosts are not easily reconfigurable • It's developed in-house and has issues
  • 8. Scenario • multiple producers • a consumer and its backup • Systems separated by 100-400ms WAN • with occasional 100% packet loss
  • 10. pymq • very hazy on the details • depends on MySQL? and Django?!? • ignored while looking at kombu / rabbitmq
  • 11. ZeroMQ aka 0MQ "ZeroMQ is a message orientated IPC Library." - commenter on stackoverflow
  • 12. AMQP • Is a standard for message queueing • Producers submit messages to brokers • Brokers consist of exchanges and queues • Exchanges route the messages • Queues store messages • Consumers pull messages out
  • 13.
  • 15. RabbitMQ Producer Broker Consumer
  • 16. RabbitMQ Producer Broker Exchange Queue Consumer
  • 29. RabbitMQ 1. Mark the exchange “durable”. 2. Mark the queue “durable”. 3. Set the message’s “delivery mode” to a value of 2
  • 32. My Desired Setup Remote Host Processing Server Publisher Queue ebs Interw Queue Consumer
  • 33. My Desired Setup Remote Host Processing Server Publisher Queue ebs Interw Queue Consumer Consumer
  • 34. My Desired Setup Remote Host Processing Server Publisher Consumer ebs Interw Queue
  • 35. Shovel Remote Host Processing Server Publisher Queue bs Queue rwe Consumer Inte Shovel
  • 36. =ERROR REPORT==== 7-Aug-2012::16:50:32 === ** Generic server <0.366.0> terminating ** Last message in was {'$gen_cast',init} ** When Server state == {state,undefined,undefined,undefined,undefined, hello_shovel, {shovel, {endpoint, [{amqp_params_direct,<<"guest">>,<<"/">>, rabbit@localhost,none,[]}], []}, {endpoint, [{amqp_params_network,<<"guest">>,<<"guest">>, <<>>,"hardrock",undefined,0,0,0,infinity,none, [#Fun<amqp_auth_mechanisms.plain.3>, #Fun<amqp_auth_mechanisms.amqplain.3>], [],[]}], []}, 0,on_confirm,#Fun<rabbit_shovel_sup.16.91344538>, #Fun<rabbit_shovel_sup.16.91344538>,<<"hello">>,5}, undefined,undefined,undefined,undefined,undefined} ** Reason for termination == ** {{badmatch,{error,access_refused}}, [{rabbit_shovel_worker,make_conn_and_chan,1,[]}, {rabbit_shovel_worker,handle_cast,2,[]}, {gen_server2,handle_msg,2,[]}, {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,227}]}]}
  • 37. error in config file "/usr/local/etc/rabbitmq/rabbitmq.config" (37): syntax error before: '.'
  • 38. Shovel [ {rabbitmq_shovel, [ {shovels, [ {hello_shovel, [ {sources, [ {brokers, ["amqp://"]} ]} , {destinations, [ {brokers, ["amqp://server"]} ]} , {queue, <<"hello">>} ]} ]} ]} ].
  • 39. [ Shovel {rabbitmq_shovel, [ {shovels, [ {hello_shovel, [ {sources, [ {brokers, ["amqp://"]} , {declarations, [ {'exchange.declare', [ {exchange, <<"foo">>} , {type, <<"direct">>} , durable ]} , {'queue.declare', [ {queue, <<"hello">>} ]} , {'queue.bind', [ {exchange, <<"foo">>} , {queue, <<"hello">>} ]} ]} ]} , {destinations, [ {brokers, ["amqp://hardrock"]} ]} , {queue, <<"hello">>} ]} ]} ]} ].
  • 40. Installation • 1. install RabbitMQ • (install homebrew; brew install rabbitmq; rabbitmq-server [-detached]) • (yum install rabbitmq-server.noarch) • rabbitmqctl or http://server:55672/ • 2. pip install kombu, or pika, or puka, or ...
  • 41. pika "a pure-Python implementation of the AMQP 0-9-1 protocol"
  • 42. Publisher import pika connection = pika.BlockingConnection(pika.ConnectionParameters('server')) channel = connection.channel() channel.queue_declare(queue='hello', durable=True) channel.basic_publish(exchange='', routing_key='hello', body='Hello World!', properties=pika.BasicProperties(delivery_mode=2)) print " [x] Sent 'Hello World!'" connection.close() Publisher Queue
  • 43. Consumer import pika connection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() channel.queue_declare(queue='hello', durable=True) print ' [*] Waiting for messages. To exit press CTRL+C' def callback(ch, method, properties, body): print ' [x] Received %r' % (body,) channel.basic_consume(callback, queue='hello', no_ack=True) channel.start_consuming() Queue Consumer
  • 44. Remote Consumer Local Publisher
  • 45. Remote queues import pika connection = pika.BlockingConnection(pika.ConnectionParameters('server')) channel = connection.channel() channel.queue_declare(queue='hello', durable=True) print ' [*] Waiting for messages. To exit press CTRL+C' def callback(ch, method, properties, body): print ' [x] Received %r' % (body,) channel.basic_consume(callback, queue='hello', no_ack=True) channel.start_consuming() Host 1 Host 2 Publisher Queue Consumer Consumer
  • 46. Remote Consumer Local Consumer Local Publisher
  • 47. Acknowledgement import pika connection = pika.BlockingConnection(pika.ConnectionParameters('server')) channel = connection.channel() channel.queue_declare(queue='hello', durable=True) print ' [*] Waiting for messages. To exit press CTRL+C' def callback(ch, method, properties, body): print ' [x] Received %r' % (body,) raw_input('Press enter to ACK') ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_consume(callback, queue='hello', no_ack=False) channel.start_consuming()
  • 48. Consumer Publisher
  • 49. Issues • pika's BlockingConnection (my use case is simple enough) hard-codes the socket timeout and fails to cope with latency >1s • Fails to cope at all with packet loss
  • 50. Deleting a Queue import pika connection = pika.BlockingConnection(pika.ConnectionParameters('server')) channel = connection.channel() channel.queue_delete(queue='hello') channel.close() connection.close()
  • 52. Publisher from kombu import BrokerConnection with BrokerConnection('amqp://localhost') as conn: with conn.SimpleQueue('hello') as queue: queue.put('Hello World!') print " [x] Sent 'Hello World!'"
  • 53. Bizarro errors amqplib.client_0_8.exceptions.AMQPChannelException: (406, u"PRECONDITION_FAILED - parameters for queue 'hello' in vhost '/' not equivalent", (50, 10), 'Channel.queue_declare')
  • 54. Publisher from kombu import BrokerConnection with BrokerConnection('amqp://localhost//') as conn: with conn.SimpleQueue('hello', queue_opts=dict(durable=False)) as queue: queue.put('Hello World!') print " [x] Sent 'Hello World!'"
  • 56. Publisher import puka client = puka.Client('amqp://localhost//') client.wait(client.connect()) client.wait(client.queue_declare(queue='hello', durable=True)) promise = client.basic_publish(exchange='', routing_key='hello', body='Hello World!') client.wait(promise) print " [x] Sent 'Hello World!'" client.wait(client.close())
  • 57. Other Plugins • Management (web interface, quite nice) • Federation (Shovel, but with MOAR) • STOMP protocol support
  • 58. STOMP Simple (or Streaming) Text Orientated Messaging Protocol
  • 60. STOMP {rabbitmq_stomp, [ {tcp_listeners, [ {"127.0.0.1", 61613} , {"::1", 61613} ]} , {default_user, [ {login, "guest"} , {passcode, "guest"} ]} ]}
  • 61. stompclient from stompclient import PublishClient client = PublishClient('localhost', 61613) client.connect() client.send('/queue/hello', 'Hello, world!') client.disconnect()
  • 62. stompclient from kombu import BrokerConnection with BrokerConnection('amqp://localhost') as conn: with conn.SimpleQueue('hello') as queue: queue.put('Hello World!') print " [x] Sent 'Hello World!'" from stompclient import PublishClient client = PublishClient('localhost', 61613) client.connect() client.send('/queue/hello', 'Hello, world!') client.disconnect()
  • 63. stompclient from stompclient import PublishClient client = PublishClient('localhost', 61613) client.connect() client.send('/queue/hello', 'Hello, world!') client.disconnect() from stompclient import PublishClient with PublishClient('localhost', 61613) as client: client.send('/queue/hello', 'Hello, world!')
  • 64. Celery "a synchronous or asynchronous task queue/job queue based on distributed message passing"
  • 65. TcpCatcher • TCP, SOCKS, HTTP(S) proxy & monitor • Can introduce latency and transmission errors • Understands HTTP and images • Can debug/interfere/log SSL traffic • Free: www.tcpcatcher.fr

Editor's Notes

  1. \n
  2. \n
  3. \n
  4. \n
  5. Network latency currently means processing slows down.\n
  6. One &quot;facility&quot; is the zipping up of multiple events into a batch and sending the zip across the WAN in one go. This obviously complicates things further and introduces additional latency onto the message transmission.\n
  7. \n
  8. \n
  9. \n
  10. ... and I never actually came back to evaluate it\n
  11. Is message queueing without a broker. Kind of like a glorified socket. Messages are routed in common MQ patterns right down at the network level. If you want store and forward, you&apos;re on your own for the persistence part.\n
  12. \n
  13. AMQP in a nutshell. I might add that amqp.org was no help whatsoever in figuring this out.\n
  14. There&apos;s a bunch of AMQP implementations out there, but in the interests of keeping my own sanity I only looked at the one most popular free implementation. Since they all end up implementing the same thing anyway.\n
  15. \n
  16. \n
  17. Queues are where your messages end up in the broker. They sit there until a client (a.k.a. consumer) connects to the queue and siphons them off. Queues may be configured so messages are discarded if there isn&amp;#x2019;t a consumer ready to accept them. Multiple consumers may connect to a queue - the messages will be passed to each consumer in turn.\n
  18. Exchanges are routers with routing tables that sit in front of queues. They&apos;re declared by consumers, just like queues, except that there&apos;s a default &quot;just pass the message to the queue&quot; exchange for the simple case. Every message has what&amp;#x2019;s known as a &amp;#x201C;routing key&amp;#x201D;, which is simply a string. The exchange has a list of bindings (routes) that say, for example, messages with routing key &amp;#x201C;X&amp;#x201D; go to queue &amp;#x201C;spam&amp;#x201D;.\n
  19. Messages come in to the broker, are routed by exchanges and stored in queues until slurped off by consumers. Within a broker you may have multiple logical systems called virtual hosts. I&apos;m not sure why. There&apos;s a default one and it&apos;s probably all I&apos;ll ever need.\nQueues and exchanges are created programmatically by your producers or consumers - not via a configuration file or command line program - your MQ configuration is in-line with your app code.\n
  20. An interesting aside for performance - exchanges all run in their own processes so adding more exchanges is a way to spread load and increase throughput.\n
  21. &amp;#x201C;routing rules&amp;#x201D; (or bindings) link an exchange to a queue based on a routing key. It is possible for two binding rules to use the same routing key. For example, maybe messages with the routing key &amp;#x201C;audit&amp;#x201D; need to go both to the &amp;#x201C;log-forever&amp;#x201D; queue and the &amp;#x201C;alert-the-big-dude&amp;#x201D; queue. To accomplish this, just create two binding rules (each one linking the exchange to one of the queues) that both trigger on routing key &amp;#x201C;audit&amp;#x201D;. In this case, the exchange duplicates the message and sends it to both queues.\n
  22. There are multiple types of exchanges. They all do routing, but they accept different styles of binding &amp;#x201C;rules&amp;#x201D;. \n
  23. A &quot;direct&quot; exchange only matches if the routing key is &amp;#x201C;dogs&amp;#x201D; or not. The default exchange is a Direct exchange.\n
  24. For example, a &amp;#x201C;topic&amp;#x201D; exchange tries to match a message&amp;#x2019;s routing key against a wildcard pattern like &amp;#x201C;dogs.*&amp;#x201D;.\n
  25. A &quot;fanout&quot; exchange ignores the routing key and distributes the messages to all queues.\n
  26. There&apos;s two levels of persistence in play in RabbitMQ: the structure of the broker and the messages in the broker&apos;s queues.\n\n
  27. You may mark your queues and exchanges as &amp;#x201C;durable&amp;#x201D; so the queue or exchange will be re-created automatically on reboot. It does not mean the messages in the queues will survive the reboot. They won&amp;#x2019;t.\n
  28. When you publish your message to an exchange, you may set a flag called &amp;#x201C;Delivery Mode&amp;#x201D; to the value 2, which means &amp;#x201C;persistent&amp;#x201D;. &amp;#x201C;Delivery Mode&amp;#x201D; usually (depending on your AMQP library) defaults to a value of 1, which means &amp;#x201C;non-persistent&amp;#x201D;.\n
  29. So the steps for persistent messaging are...\nIf you bind a durable queue to a durable exchange, RabbitMQ will automatically preserve the binding. Similarly, if you delete any exchange/queue (durable or not) any bindings that depend on it get deleted automatically.\n
  30. RabbitMQ will not allow you to bind a non-durable exchange to a durable queue, or vice-versa. Both the exchange and the queue must be durable for the binding operation to succeed.\nYou cannot change the creation flags on a queue or exchange after you&amp;#x2019;ve created it. For example, if you create a queue as &amp;#x201C;non-durable&amp;#x201D;, and want to change it to &amp;#x201C;durable&amp;#x201D;, the only way to do this is to destroy the queue and re-create it. It&amp;#x2019;s a good reason to double check your declarations\n
  31. Sometimes you will want your consumer to process the message before removing it from the queue. For example if you&apos;re sending billing through the queue then you don&apos;t want to lose the billing details just because the client died while processing the message. You can do this by turning off auto-acknowledgement. By setting no_ack to False. Yes, no_ack. To indicate that the broker should automatically ack, you pass no_ack=True. W.T.F. It defaults to False, BTW. So if you want to manually acknowledge, you must use no_ack=False.\n
  32. This is my typical setup - I have hosts separated by network (WAN) out of my control. I need all the events generated on the remote hosts to be processed in a timely, reliable manner by the processing server.\n
  33. One solution is to write a forwarding consumer on the remote host - pretty simple code but not very elegant.\n
  34. An alternative setup we could use with the processing server consumer pulling from all the remote host queues. This makes it more configuration work when adding new remote hosts though.\n
  35. Then I discovered the Shovel plugin. I&apos;ve ignored exchanges up until now, but using Shovel allows an exchange on one host to pull messages from a queue and fire them at another queue. It basically runs an erlang client in the remote broker to forward the messages. In theory. In practise...\n
  36. Look hard - it says &quot;Fun&quot; in there. This is NOT FUN. This was bloody hard to figure out. The main problem is that once you decide you&apos;re going to use Shovel, you&apos;re now programming Erlang. See previous statement about fun.\n
  37. Not only am I now learning Erlang but the errors you get back for malformed configuration files (Erlang programs) are really unhelpful. This error basically says &quot;there&apos;s an error somewhere in the 37 lines of your program.&quot;\n
  38. This is my minimum shovel configuration, eventually discovered after much trial-and-error. I shall not share with you the entire volume of bizarre and obscure errors and warnings I waded through to get to this point, nor the number of dead-end alleyways the poor documentation led me down. Unfortunately when you start up the server with this configuration the log file will FILL with warnings about the queue not existing until a client connects and creates the queue.\n
  39. This would probably be simpler if I was familiar with Erlang, but I found the documentation to be basically impenetrable. Also, for some reason I couldn&apos;t declare the queue without declaring an exchange. Which isn&apos;t needed if I don&apos;t declare the queue. There was an awful lot of stumbling around in the dark to get this working, but in the end it does.\n
  40. Default login is guest/guest...\n
  41. It tries to stay fairly independent of the underlying network support library. It uses amqplib underneath by default, which is what most of the libraries do.\n
  42. This code connects to our RabbitMQ server using a blocking connection (send and wait for successful delivery at server before continuing); it declares a durable &quot;helllo&quot; queue and publishes a simple message to the queue. The queue and undelivered messages will be persistent across restarts of RabbitMQ. It&apos;s a slightly bizarrely wordy API. The exchange argument is required, but we use the &quot;no-op&quot; or &quot;default&quot; exchange here. More on them later.\n
  43. This code connects to our RabbitMQ server using a blocking connection (listen and wait for messages); it also declares a &quot;helllo&quot; queue (just in case no publisher is connected) and consumes messages from the queue. You can see that a bunch of the code is the same - connections, channels and queues. Note we&apos;re not going to be manually acknowledging these messages.\n
  44. Here we see the publisher running on my laptop (local) and the consumer running on the server where the RabbitMQ server is also running. You can see that we can publish into the queue without anything consuming the messages, and we can consume published events immediately. We can also listen as a consumer with no publisher publishing. It&apos;s all quite disconnected.\n
  45. By making one small change to our consumer, we can consume remote queues.\n
  46. Here we set up a second consumer that will consume the remote queue on the server from the local host. Messages published to the queue will be passed to each consumer in turn round-robin style. When a consumer stops consuming the queue will transparently feed all messages to the remaining consumer. And of course this extends to having multiple publishers as well.\n
  47. We lose the &quot;no_ack=True&quot; so acks are used, and then in the processing once we&apos;re done we basic_ack the message using the &quot;delivery tag.&quot;\n
  48. So, now when we retrieve messages from the queue we have to ack them manually. If we don&apos;t and the program exits then we&apos;ll get the message again when the program starts consuming messages. Note I&apos;ve modified the publisher to generate a unique-ish message each time.\n
  49. Can fix the hard-coded socket timeout issue, and a try/except might be able to handle the packet loss.\n
  50. If you set up a queue with the wrong parameters you&apos;ll need to delete it. For some unknown reason the rabbitmq control program doesn&apos;t provide the ability to delete queues, so you need to do it from a client. This code does that.\n
  51. Kombu is a messaging framework for Python. It replaces Carrot.\nThe aim of Kombu is to make messaging in Python as easy as possible by providing an idiomatic high-level interface for the AMQ protocol, and also provide proven and tested solutions to common messaging problems. Its &quot;transports&quot; include AMQP variations and non-AMQP &quot;virtual transports&quot; such as Redis, MongoDB, CouchDB and Beanstalk or &quot;database transports&quot; such as SQLAlchemy and Django ORM.\n
  52. This took me some time to write as the documentation for Kombu is quite limited. Attempting to set things up using channels lead nowhere. I couldn&apos;t find clear documentation on how to create a channel. In the end I found the SimpleQueue which worked after some effort, but I&apos;m still not clear on the details. Then I discovered that the default queue parameters were different (see next slide.)\n
  53. When I was testing early on I wasn&apos;t using durable queues. kombu&apos;s SimpleQueue sets durable to True by default which caused the above bizarro error (which basically says I&apos;m trying to use a queue with different parameters to those it was created with.) This error is not specific to Kombu, but it was unexpected and inexplicable when I first encountered it until I guessed at the durable parameter setting.\n
  54. Took me a while to figure out how to disable durable.\n\nBut again, there&apos;s no channel - it&apos;s really just API noise for simple code like this.\n
  55. The puka module implements a client for AMQP 0-9-1 protocol. It&amp;#x2019;s tuned to work with RabbitMQ broker, but should work fine with other message brokers that support this protocol. It tries to be a nicer API than pika, which is honestly quite appalling.\n
  56. Everything in puka works off the Client which is quite different but pretty convenient. The API is basically the same as pika at the business end. The big difference is in the promises and the ability to wait on the promised action being completed successfully. Puka wants to be asynchronous - the wait() calls effectively force it to be synchronous for simple code like this.\nI needed to patch puka version 0.0.5 as mentioned in issue #15 on their tracker to fix a connection-time issue. Unfortunately even with that fix this was still fragile and inexplicably stopped working at one point. Puka also does away with channels like kombu&apos;s simple case.\n
  57. STOMP is the Simple (or Streaming) Text Orientated Messaging Protocol\n
  58. &quot;STOMP is a very simple and easy to implement protocol, coming from the HTTP school of design; the server side may be hard to implement well, but it is very easy to write a client to get yourself connected. For example you can use Telnet to login to any STOMP broker and interact with it!&quot;\n
  59. The STOMP website kinda mirrors the AMQP website: there&apos;s a specification there but little else. Not so simple. Fortunately there&apos;s a bunch of Python STOMP client libraries.\n
  60. Enabling STOMP was easy enough in the RabbitMQ configuration file - the docs were much clearer and the configuration much simpler than Shovel.\n
  61. So here&apos;s one Python library, stompclient, publishing to my &quot;hello&quot; queue. \n
  62. So... not a whole lot simpler...\n
  63. I made a small change to the stompclient library to allow this usage, which I think is pretty darned simple - I believe it&apos;ll be in the next release. I&apos;m not completely sold on STOMP yet though. I&apos;m not sure it improves things over AMQP enough to switch from just using Kombu.\n
  64. RPC engine. It is focused on real-time operation, but supports scheduling as well. The execution units, called tasks, are executed concurrently on a single or more worker servers. It&apos;s built over kombu and a variety of non-AMQP backends. The RPC nature and backend generality limit the abilities of MQ somewhat, though is nice if you&apos;re just after worker management (which I&apos;m not.)\n
  65. I found this worked sometimes, but not other times. RabbitMQ did NOT like me putting this in the middle of the Shovel setup, but the Python libraries I used were happy to use it as a proxy.\n