Archive for the ‘AMQP’ tag

Consuming AMQP/RabbitMQ messages in Python is simple if you use Sparkplug. I read “Building RabbitMQ apps using Python“, and there’s just too much code in the monitor method and the separation of concerns aren’t very clear.

With Sparkplug, you create a configuration file, then define Consumer class to handle each message. As messages are pushed into the queue, Sparkplug will call your class and you decide how you want handle the message in the __call__ method. The great thing about this is that all the connection logic is removed from your code letting you concentrate on how you want to handle each message.

Now you can run your app using sparkplug --daemon consumer.ini. Configuration is boring, so I’ve left the consumer.ini out of the blog post and put it up on github instead.

Introduction
As stock markets open, order management systems are flooded with new orders and it’s crucial that an OMS not miss prices or drop orders during this period.  The purpose of this initial benchmark is to simulate a flood of orders hitting the queue.

Benchmark
The benchmarking script sets up 10 queues, 10 producers and 10 consumers, each producer writes to a single queue and each consumer reads from that queue ie: p1 writes to q1 and c1 reads from q1 as fast at it can.  The time measured is the time it takes a message to travel from p1 to the queue and to be read by c1 and it was calculated by appending the timestamp to the message itself.

I chose to run a series of tests with message size varying from 35 bytes to 400 bytes and the message count varying from 50 messages to 100 messages in an attempt to visualize the broker’s behavior under varying conditions.

The benchmark was performed using a server running 2.8GHz Pentium D with 903464 kB RAM running on Kernel 2.6.18-128.1.10.el5 using RabbitMQ 1.5.5 and a machine with similar specifications as the client—both the producer and consumer run on the same machine.  The network is a typical Fast Ethernet with two switches separating the server and client machines.

RabbitMQ

Conclusion
Inconclusive! The numbers are very surprising I wasn’t expecting the message transfer times to be greater than .5 seconds under this load.  It’s possible that the consumer may not be able to keep up with flood of messages, if that’s the case than a consumer written in C# is needed.  What is obvious is that more tests  with a constant message size and a varying number of messages  are needed.

The standard deviation is also greater than I expected, so I plan on creating longer running tests and see if the broker falls into a steady state.  Finally, I also want to test with 50 messages per producer using 20 queues/producers instead of 10  and see how RabbitMQ responds.

I’m wondering what sort of performance others are experiencing—any and all feedback is greatly appreciated.

Postscript
I intended on using C# to benchmark RabbitMQ but for want of time  I used a modified version of Colin Surprenant‘s bunnypunisher ruby script.  There’s a slightly outdated (and dirty) version of the script available on github.  I will upload the latest version along with the “launcher” tomorrow morning.

Kyle Burton at Asymmetrical View has a fairly comprehensive comparison of RabbitMQ and Qpid.

Overview
Performance is vital in the world of stock trading, you can easily lose hundreds of thousands of dollars if the trading platform you’re using routes orders to the stock exchanges too slowly and you miss the your target price.

The order management system I work on uses IRC as the messaging middle ware– a message is sent to a channel and another process reads and processes the message.  This gives us great flexibility, letting us write the user interface in .NET and the back-end server code in whichever language we choose and it also allows us to scale the system by moving processes to different machines.

But this setup has problems, if a message is missed by a process, there’s no easy to way to retrieve it and recent benchmarking showed that the latency of the messaging system spikes, unpredictably to 300 ms or more.  Initially IRC made sense but the requirements have grown and it’s clear a more robust solution which provides greater reliability, performance and scalability is needed.

AMQP
The Advanced Message Queuing Protocol (AMQP) is an open standard, vendor neutral binary protocol for messaging middleware. AMQP features: messages, queuing and routing and it was designed by the financial industry to replace existing proprietary message queues.  It seems to be the Promised Land—the perfect replacement for IRC.

After a quick evaluation of messaging brokers, the best candidates appear to be RabbitMQ and Apache Qpid. Both support AMQP, seem to have low latency and have vendor support—Qpid in the form of RedHat MRG.  While both seem to be faster than IRC, I needed to be sure.

AMQP is more complicated than IRC and replacing the current messaging system won’t be easy. I wanted to create a benchmark that simulates the load we see in a production environment, but before I could create the test, I need to better understand what AMQP provides and the terminology it uses.

AMQP Features

Messages are glorified strings which are published to an exchange. They consist of a header and a content body, while headers have several properties; you only need to know one to get started: the routing-key, a field used by exchanges to determine which queue the message will be routed to.

Queues are where your messages wait until they are consumed.  Queues can be configured to let messages die if a consumer is not available, queues along with exchanges can be made durable.  Message can persists if the queue and the exchange are marked as durable and the message’s delivery mode is set to persistent.

Exchanges the help the broker decide which queue to route your message to.  While they’re slated for removal in AMQP  1.0,  but they’re still important and difficult to ignore– there are four types of exchanges:  Fanout, Direct, Topic and Header.

  • Direct exchange: Use routing keys, messages sent to a direct exchange are routed to exchanges where the routing key matches exactly.
  • Topic exchange: A hierarchical exchange which also uses routing keys, routing keys are matched against a pattern, the hierarchy is established by separating keywords with the dot symbol.
  • Fanout Exchange: A 1:N exchange, any message sent to an exchange is sent to all queues bound to that exchange.

A Channel is to AMQP what session is to HTTP, I’m not sure if that’s very accurate– all communication over a channel is stateful, and each instance of your program will have at least one channel.

Conclusion
There’s a lot to digest, I spent the better part of the day reading RabbitMQ’s .NET API Guide.  In part two of this series I’ll walkthrough C# client and benchmark RabbitMQ.  As always, your feedback and comments are appreciated.

Search