Understanding Message Broker in Microservices Design: A starters guide
Development

Understanding Message Broker in Microservices Design: A starters guide

By Hany Mamdouh | CEO | AtenTEC5 min read

Implementing a Message Broker with Go: A Comprehensive Guide

In this article, we'll dive into the process of implementing a Message Broker using RabbitMQ and Go. Additionally, we'll explore the conventions and principles we use for building scalable messaging systems.

Key Components of a Messaging System

Before we jump into the implementation details, it's essential to understand the core components that form the foundation of a messaging system. While this article focuses on RabbitMQ, the concepts here apply to many other message brokers as well. The major components of a messaging system are:

  • Message Broker Server
  • Exchanges
    • Fanout
    • Topic
    • Direct
  • Queues
  • Events
    • Routing Keys
    • Binding Keys

Message Broker Server

A Message Broker Server is responsible for receiving messages from producers, holding them, and distributing them to the appropriate consumers. In our case, we use RabbitMQ as the message broker. It plays a crucial role in decoupling different services, enabling efficient communication across microservices. Exchanges

An exchange in RabbitMQ serves as a message router, directing messages from producers to consumers based on predefined routing rules. Think of it as a network switch or a post office that ensures messages reach the correct destinations (queues).

Each microservice within your architecture can have its own set of exchanges, each responsible for routing events related to specific entities. For instance, in a Fleet microservice responsible for managing a fleet of cars, events like adding, updating, or deleting cars would be published under different exchanges.

A typical naming convention for exchanges could be:

  • Simple systems: <entityName>.<eventName>
  • Complex systems: <microserviceName>.<entityName>.<eventName>

Using the microservice name as a prefix allows you to avoid naming collisions, especially when multiple services define the same entity. For example, both the Fleet and History microservices might handle the car entity but publish different types of events. Types of Exchanges

RabbitMQ supports several types of exchanges, each serving different purposes:

Fanout Exchange

A fanout exchange broadcasts messages to all queues bound to it, without any consideration for routing keys. This is useful when you need all consumers to receive the same message—think of it as a broadcast mechanism.

Topic Exchange

The topic exchange allows consumers to filter the messages they want to receive based on routing patterns. It’s useful when events belong to a specific category, and consumers only care about a subset of those events.

For example, in a Fleet microservice that handles car events (e.g., car added, car updated), consumers can subscribe to specific events like car.added or car.updated. The key here is the routing key, which follows a <entity>.<event> pattern, allowing for the use of wildcards. Consumers can then specify patterns (e.g., car.* or car.added) to filter the events they want to consume.

Direct Exchange

A direct exchange sends messages to specific queues based on an exact match between the routing key and the queue's binding key. It’s ideal for point-to-point communication, where each message should be routed to a particular queue without any wildcard matching.

Queues

Queues are where messages are stored until they are consumed. A queue binds to an exchange and filters the messages it receives based on its binding rules. Queues work as buffers that temporarily hold messages before they’re processed by consumers.

The naming convention for queues is important for ensuring clarity and uniqueness. We recommend using the format <consumerName>.<eventName>. For example, floor.car.added would indicate that the floor microservice is consuming the car.added event.

Queues are linked to exchanges via binding keys, which determine which messages (events) the queue will consume. Events, Routing Keys, and Binding Keys

In a message-driven architecture, events represent business-level changes within your microservices. While we don't send "events" directly, we publish them as messages with routing keys, and the server takes care of routing them to the appropriate queues.

  • Routing Key: This key is set by the producer when publishing a message. It indicates the event, such as car.added or car.updated.
  • Binding Key: The consumer sets the binding key when it binds its queue to an exchange. The binding key defines the pattern that determines which messages (events) are routed to the queue.

The server filters messages based on the routing key and binding key. This allows consumers to subscribe to specific events or patterns, depending on their needs.

For instance, a car.added routing key could be filtered by a queue with a car.* binding key to receive all car-related events, or car.added for more granular control. Putting It All Together

To summarize, here's how the system works:

  • Producers publish messages with routing keys to exchanges.
  • Exchanges route messages to queues based on the routing and binding keys.
  • Consumers process messages from their queues, acting on specific events.

A well-structured message broker system can decouple your services, making your application more scalable and maintainable. Using a tool like RabbitMQ with Go ensures that your messaging system remains efficient and reliable, even as your application grows.

Category

Development

Tags

Message Broker
Architecture
Development
System Design
Hany Mamdouh | CEO | AtenTEC

Hany Mamdouh | CEO | AtenTEC

As the Co-Founder and CEO of Anchornize and CEO of AtenTEC, I bring over 20 years of experience in software engineering, solution architecture, and business management. I specialize in leading enterprise-level software projects, developing innovative solutions, and aligning technology with business objectives to drive growth and efficiency.

Related Articles

Mastering Modern Authentication: A Guide to Secure Communication
5 min read

Mastering Modern Authentication: A Guide to Secure Communication

This article provides a practical guide to modern authentication patterns using OIDC and OAuth 2.0. Through three easy-to-understand sequence diagrams, it visualizes the secure flows for backend-to-backend communication, frontend-to-backend user logins with stateful sessions, and a combined scenario where a backend service makes a B2B call to fulfill a frontend request. It explains the core concepts of token exchange, session management, and role-based access control (RBAC), making these complex interactions accessible to developers and system architects.

Background

Stay in the loop

Need to know more? book a consultation meeting now