DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

  1. DZone
  2. Data Engineering
  3. Data
  4. RabbitMQ in Microservices

RabbitMQ in Microservices

Learn how to use the RabbitMQ message broker to enable communication between your distributed systems, promoting loosely-coupled microservices.

By 
Akash Bhingole user avatar
Akash Bhingole
·
Sep. 06, 18 · Tutorial
Likes (56)
Comment (17)

Save
Tweet
Share
80.28K Views

Join the DZone community and get the full member experience.

Join For Free

RabbitMQ, also known as Open-Source Message Broker, supports multiple message protocols and can be deployed on distributed systems. It is lightweight and makes it easy to deploy applications. It mainly acts as a queue where a message which is entered can first be operated on. RabbitMQ runs on many operating systems and cloud environments and provides a wide range of developer tools for most popular languages. It is a Producer-Consumer style pattern where the producer sends a message and the consumer consumes it. The main features of RabbitMQ are mentioned below:

  1. Asynchronous Messaging

  2. Distributed Deployment

  3. Management & Monitoring

  4. Enterprise- and Cloud-Ready

Installation

For RabbitMQ, you first need to have ErLang installed in your system as the RabbitMQ program is written in the ErLang programming language. After ErLang, you can download the latest version of RabbitMQ from its home site by following instructions given there.

Use of RabbitMQ in Microservices

RabbitMQ is one of the simplest freely available options for implementing messaging queues in your microservices architecture. These queue patterns can help to scale your application by communicating between various microservices. We can use these queues for various purposes, like interaction between core microservices, decoupling of microservices, implementing failover mechanisms, and sending email notifications via message brokers.

Wherever two or more core modules need communicate with each other, we should not make direct HTTP calls, as they can make the core layer tightly coupled and it will be difficult to manage when there are more instances of each core module. Also, whenever a service is down, the HTTP call pattern will fail, as after a restart, there is no way to track old HTTP request calls. This results in the need for RabbitMQ. 

Image title

Setting Up RabbitMQ in Microservices

In microservice architecture, for this demonstration, we will use an example pattern of sending email notifications via various core microservices. In this pattern, we will have a producer, any of the core microservices, which will generate the email content and pass it on to the queue. Then this email content is taken by the consumer, who is always listening to the queue for new messages.

Please note that we are using Spring Boot for our microservices, so we will be doing configuration provided for Spring.

1) Producer: This layer is responsible for the generation of email content and passing on this content to the message broker in RabbitMQ.

a) In the properties file, we need to mention the queue name and exchange types along with the host and port where the RabbitMQ server is installed.         

1
queue.name=messagequeue
2
fanout.exchange=messagequeue-exchange
3
spring.rabbitmq.host: localhost
4
spring.rabbitmq.port: 5672
5
spring.rabbitmq.username: guest
6
spring.rabbitmq.password: guest

     

b) We need to create one configuration class, which will use the queue name and exchange type to bind the queue to the microservice module. 

​x
1
@Configuration
2
public class RabbitConfiguration {
3
​
4
 @Value("${fanout.exchange}")
5
 private String fanoutExchange;
6
​
7
 @Value("${queue.name}")
8
 private String queueName;
9
​
10
 @Bean
11
 Queue queue() {
12
  return new Queue(queueName, true);
13
 }
14
​
15
 @Bean
16
 FanoutExchange exchange() {
17
  return new FanoutExchange(fanoutExchange);
18
 }
19
​
20
 @Bean
21
 Binding binding(Queue queue, FanoutExchange exchange) {
22
  return BindingBuilder.bind(queue).to(exchange);
23
 }
24
​
25
}


c) Finally, we need one util class, which will be used to send actual email content to the queue using RabbitTemplate, provided by the Spring framework. 

24
1
@Component
2
public class QueueProducer {
3
​
4
 protected Logger logger = LoggerFactory.getLogger(getClass());
5
​
6
 @Value("${fanout.exchange}")
7
 private String fanoutExchange;
8
​
9
 private final RabbitTemplate rabbitTemplate;
10
​
11
 @Autowired
12
 public QueueProducer(RabbitTemplate rabbitTemplate) {
13
  super();
14
  this.rabbitTemplate = rabbitTemplate;
15
 }
16
​
17
 public void produce(NotificationRequestDTO notificationDTO) throws Exception {
18
  logger.info("Storing notification...");
19
  rabbitTemplate.setExchange(fanoutExchange);
20
  rabbitTemplate.convertAndSend(new ObjectMapper().writeValueAsString(notificationDTO));
21
  logger.info("Notification stored in queue sucessfully");
22
 }
23
​
24
}


d) Then you can call a produce method from anywhere in the module.

3
1
{
2
  queueProducer.produce(notificationDTO);
3
}


2) Consumer: This layer is responsible for consuming the message from the RabbitMQ message broker with the FIFO method, then performing email-related operations.

a) In the properties file, we need to mention the queue name and exchange types, along with the host and port where the RabbitMQ server is installed.       

6
1
queue.name=messagequeue
2
fanout.exchange=messagequeue-exchange
3
spring.rabbitmq.host: localhost
4
spring.rabbitmq.port: 5672
5
spring.rabbitmq.username: guest
6
spring.rabbitmq.password: guest


b) We need to create one configuration class, which will use the queue name and exchange type to bind the queue to the microservice module. Also, in the consumer's RabbitMQ configuration, we will need to create a MessageListenerAdapter bean, which will make it act as a consumer and always listen for the incoming message in queue pipeline. This MessageListenerAdapter will have a parameterized constructor with a Consumer util class and defaultListenerMethod, where we can specify email-related operations.

43
1
@Configuration
2
public class RabbitConfiguration {
3
​
4
 private static final String LISTENER_METHOD = "receiveMessage";
5
​
6
 @Value("${queue.name}")
7
 private String queueName;
8
​
9
 @Value("${fanout.exchange}")
10
 private String fanoutExchange;
11
​
12
​
13
 @Bean
14
 Queue queue() {
15
  return new Queue(queueName, true);
16
 }
17
​
18
 @Bean
19
 FanoutExchange exchange() {
20
  return new FanoutExchange(fanoutExchange);
21
 }
22
​
23
 @Bean
24
 Binding binding(Queue queue, FanoutExchange exchange) {
25
  return BindingBuilder.bind(queue).to(exchange);
26
 }
27
​
28
 @Bean
29
 SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
30
  MessageListenerAdapter listenerAdapter) {
31
  SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
32
  container.setConnectionFactory(connectionFactory);
33
  container.setQueueNames(queueName);
34
  container.setMessageListener(listenerAdapter);
35
  return container;
36
 }
37
​
38
 @Bean
39
 MessageListenerAdapter listenerAdapter(QueueConsumer consumer) {
40
  return new MessageListenerAdapter(consumer, LISTENER_METHOD);
41
 }
42
​
43
}

   

c) Then, we need to create the QueueConsumer class which will have the specified message listener method where we can do actual email sending operations.

33
1
@Component
2
public class QueueConsumer {
3
​
4
 @Autowired
5
 MailServiceImpl mailServiceImpl;
6
 protected Logger logger = LoggerFactory.getLogger(getClass());
7
​
8
 public void receiveMessage(String message) {
9
  logger.info("Received (String) " + message);
10
  processMessage(message);
11
 }
12
​
13
 public void receiveMessage(byte[] message) {
14
  String strMessage = new String(message);
15
  logger.info("Received (No String) " + strMessage);
16
  processMessage(strMessage);
17
 }
18
​
19
 private void processMessage(String message) {
20
  try {
21
   MailDTO mailDTO = new ObjectMapper().readValue(message, MailDTO.class);
22
   ValidationUtil.validateMailDTO(mailDTO);
23
   mailServiceImpl.sendMail(mailDTO, null);
24
  } catch (JsonParseException e) {
25
   logger.warn("Bad JSON in message: " + message);
26
  } catch (JsonMappingException e) {
27
   logger.warn("cannot map JSON to NotificationRequest: " + message);
28
  } catch (Exception e) {
29
   logger.error(e.getMessage());
30
  }
31
​
32
 }
33
}


Conclusion

Using RabbitMQ, you can avoid direct HTTP calls between services and remove tight coupling of core microservices. This will help you in scaling your microservices at a higher level and add failover mechanisms between microservices.

microservice Spring Framework

Opinions expressed by DZone contributors are their own.

Partner Resources

×

    September 12, 2018 Weekly Digest

  • RabbitMQ in Microservices

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!