Routing Topologies for Performance and Scalability with RabbitMQ
Designing a good routing topology for a highly-scalable system can be like mapping a graph. Many things need to be considered, for instance the problem, constraints of the environment, those of the messaging implementation, and performance strategies. What we often run up against is a lack of flexibility and expressivity in fitting routing to our needs. Here is where RabbitMQ stands out.
Basic Concepts
Anyone familiar with messaging in general knows the concept of routing messages from A to B. Routing can be simplistic or quite complex, and when designing a routing topology for a scalable, complex system it must be elegant. Kept clean and decoupled, components can throttle nicely with varying loads. This can be expressed as a simple map or complex graph. In its simplest form a routing topology can be expressed as nodes, for instance hierarchical nodes: For those new to RabbitMQ or AMQP (note that Rabbit works with many protocols including STOMP, HTTP, HTTPS, XMPP, and SMTP), here are some basic component descriptions:- Exchange The entity within the server which receives messages from producer applications and optionally routes these to message queues within the server
- Exchange type The algorithm and implementation of a particular model of exchange. In contrast to the "exchange instance", which is the entity that receives and routes messages within the server
- Message queue A named entity that holds messages and forwards them to consumer applications
- Binding An entity that creates a relationship between a message queue and an exchange
- Routing key A virtual address that an exchange may use to decide how to route a specific message
api.agents.agent-{id}.operations.{operationName}
In more complex cases the routing key may be combined with routing on message header fields and/or its content. An exchange examines a message's properties, header fields, body content, and possibly data from other sources, then decides how to route the message. A binding pattern derived from the above routing key idea might look like api.agents..operations.
where we bind exchange E1
to queue Q1
with binding pattern api.agents..operations.
so that any messages sent to E1
route to Q1
…