Queuing with RabbitMQ and PHP

« »

There are many times that you want to write background processes and queue up the tasks so that they can be handled in sequential order. There are any number of queues available for software developers, and one that I’ve really taken a liking to is RabbitMQ. Besides the fact that the queue is designed to requeue messages that are unsuccessfully delivered, RabbitMQ is fast and efficient.

This week I’ll be describing how to implement RabbitMQ in a PHP application. There’s a lot to cover, so this will be a three-part series to help you understand RabbitMQ’s unique style (as well as understand AMQP, the protocol behind RabbitMQ). The other posts will publish tomorrow and Thursday. Let’s dive right in.

What is a connection? What is a channel?

RabbitMQ has a typical “connection” which is a TCP/IP connection to the RabbitMQ server. However, RabbitMQ is a bit more complicated, introducing a concept called the channel.

A channel is almost a “connection-within-a-connection”. This special connection is akin to a transaction between the client and the RabbitMQ server, but treating it like a transaction is a bit of a misnomer.

An open channel helps prevent TCP/IP connection timeouts, and also reduces TCP/IP connections while still allowing atomic communications from multiple workers over the same channel. The documentation indicates that a channels are “lightweight connections that share a single TCP connection”.

A connection to RabbitMQ is insufficient; a channel must be open to read from or write to RabbitMQ.

A RabbitMQ Exchange

RabbitMQ also has a concept called the “exchange”. An exchange is defined as a mechanism that “…take(s) a message and route(s) it into zero or more queues.”

Exchanges are essentially defined to hold queues. Queues are bound to exchanges. And exchanges are designated to behave in certain ways.

For example, exchanges can be designed to evenly distribute tasks among available consumers (a direct exchange). An exchange can also send out the same message to all workers (a fanout exchange) or send certain messages to certain members based on a pre-determined criteria (a topic exchange).

By default, an exchange doesn’t survive a restart of RabbitMQ, or the unsubscription of all workers (e.g. if all workers die or are shut down, the exchange is deleted and so is all the data inside the queue). But exchanges can be declared durable, which means they will survive until they are deleted, purged or run out of instructions for the workers to do.

One Exchange, Many Queues

In RabbitMQ, queues are part of exchanges (they’re bound to the exchange). Queues can also be marked as durable, and queues are actually what store the messages (not unlike a database table).

Publish to Exchange, Consume a Queue

The hardest thing to realize in RabbitMQ is that you don’t actually publish messages to a queue; you publish them to the exchange.

When publishing to the exchange, the exchange will use the rules it knows to route the message to the right queue. There are opportunities to create extremely complicated routings, although most often you’ll end up creating simple one exchange per queue settings.

But you do consume the queue. The consumer knows about a specific queue and consumes messages from the queue based on the queue rules (certain consumers can consume certain routing keys but not others, for example).

Installing AMQP and RabbitMQ for PHP

RabbitMQ has a great set of instructions for installing RabbitMQ from their own package distribution; this is the easiest way to get the newest RabbitMQ features. You can grab these directions in the documentation.

Once RabbitMQ is installed, you’ll need to install the AMQP PECL package. This package will need the dev headers for RabbitMQ (librabbitmq-dev). The PECL package is pretty simple to install (pecl install amqp) and the PHP documentation for the AMQP package is sparse, but complete.

Next, we’ll discuss building a publisher followed by a discussion on building consumers for RabbitMQ.

See more in the RabbitMQ documentation

RabbitMQ has great documentation. You can read more about the AMQP spec and RabbitMQ’s implementation here.

Brandon Savage is the author of Mastering Object Oriented PHP and Practical Design Patterns in PHP

Posted on 5/28/2013 at 7:00 am
Categories: PHP

Tarique Sani (@tariquesani) wrote at 5/28/2013 11:40 pm:

What is your opinion on Gearman Vs. RabbitMQ?

I used the former but requeing appears to be one killer feature which makes me think more in favour of RabbitMQ

Brandon Savage (@brandonsavage) wrote at 5/29/2013 8:26 am:

For me, RabbitMQ’s ability to requeue failed messages is a huge plus. I believe Gearman will requeue if your worker exits with a non-zero exit code, but that will also create problems for supervisord.

On the other hand, the docs for Gearman seem better and more prevalent.

scott wrote at 5/30/2013 8:08 am:

Brandon great article ! btw… do you have any examples of web applications you have developed with php and using Rabbitmq ?

Brandon Savage (@brandonsavage) wrote at 5/30/2013 8:33 pm:

don’t have any specific examples that are public, no. I’ve developed with Python and RabbitMQ.

Steve (@sjclemmy) wrote at 6/13/2013 4:22 am:

I setup a Codeigniter – PHP – RabbitMQ system last year and I used this library [https://github.com/videlalvaro/php-amqplib] as I couldn’t get the PECL one to install properly. It was really easy to use and I was also really impressed with the fault tolerance of RabbitMQ. The application I used it with was http://www.popsapp.com. The thumbnail creation on file uploads is handed off to RabbitMQ, so there is no blocking. It works a treat.

« »

Copyright © 2024 by Brandon Savage. All rights reserved.