Introduction
The Asynchronous communication between microservices using .NET Core API, RabbitMQ, and Docker is a common pattern for building scalable and decoupled systems. Here’s a step-by-step guide with a code example:
Step 1: Create Microservices
For the sake of this example, let’s create two microservices: OrderService
and EmailService
.
Step 2: Set Up RabbitMQ
- Install the RabbitMQ server or use a Docker container:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
- Access the RabbitMQ management dashboard at
http://localhost:15672
. Useguest
as both username and password (this is for development purposes; in production, you’d configure secure credentials).
Step 3: Create the OrderService
- Create a new .NET Core API project named
OrderService
. - Install the NuGet package
RabbitMQ.Client
:
dotnet add package RabbitMQ.Client
- Configure the
Startup.cs
to set up RabbitMQ:
using RabbitMQ.Client;
// ...
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton(factory => new ConnectionFactory
{
HostName = "localhost", // RabbitMQ server hostname
Port = 5672, // Default RabbitMQ port
UserName = "guest",
Password = "guest"
});
services.AddSingleton<IConnection>(sp => sp.GetRequiredService<ConnectionFactory>().CreateConnection());
services.AddSingleton(sp => new OrderMessageProducer(sp.GetRequiredService<IConnection>()));
}
- Create a
OrderMessageProducer
class to send messages:
using RabbitMQ.Client;
using System.Text;
public class OrderMessageProducer
{
private readonly IConnection _connection;
public OrderMessageProducer(IConnection connection)
{
_connection = connection;
}
public void SendOrderMessage(string message)
{
using (var channel = _connection.CreateModel())
{
channel.QueueDeclare(queue: "order_queue",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var body = Encoding.UTF8.GetBytes(message);
channel.BasicPublish(exchange: "",
routingKey: "order_queue",
basicProperties: null,
body: body);
}
}
}
- In your controller, inject
OrderMessageProducer
and send a message:
[ApiController]
[Route("api/[controller]")]
public class OrderController : ControllerBase
{
private readonly OrderMessageProducer _messageProducer;
public OrderController(OrderMessageProducer messageProducer)
{
_messageProducer = messageProducer;
}
[HttpPost]
public IActionResult Post([FromBody] OrderDto order)
{
// ... save order ...
// Send a message to RabbitMQ
_messageProducer.SendOrderMessage($"New order: {order.OrderId}");
return Ok();
}
}
Step 4: Create the EmailService
- Create a new .NET Core API project named
EmailService
. - Configure the
Startup.cs
to set up RabbitMQ as before. - Create a
EmailMessageConsumer
class to consume messages:
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
public class EmailMessageConsumer
{
private readonly IConnection _connection;
public EmailMessageConsumer(IConnection connection)
{
_connection = connection;
}
public void StartListening()
{
using (var channel = _connection.CreateModel())
{
channel.QueueDeclare(queue: "order_queue",
durable: false,
exclusive: false,
autoDelete: false,
arguments: null);
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body;
var message = Encoding.UTF8.GetString(body);
Console.WriteLine($"Received order message: {message}");
};
channel.BasicConsume(queue: "order_queue",
autoAck: true,
consumer: consumer);
}
}
}
- In the
Startup.cs
, add theEmailMessageConsumer
to the service container and start listening:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddSingleton(sp => new EmailMessageConsumer(sp.GetRequiredService<IConnection>()));
}
- In the
Program.cs
, start the listener when the application starts:
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
// Start the RabbitMQ message listener
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var emailMessageConsumer = services.GetRequiredService<EmailMessageConsumer>();
emailMessageConsumer.StartListening();
}
host.Run();
}
// ...
}
Step 5: Run Microservices in Docker Containers
- Build Docker images for each microservice:
docker build -t orderservice -f path/to/OrderService/Dockerfile .
docker build -t emailservice -f path/to/EmailService/Dockerfile .
- Run Docker containers for each microservice:
docker run -d --name orderservice orderservice
docker run -d --name emailservice emailservice
Step 6: Test the Communication
- Send a POST request to the
OrderService
API to simulate creating a new order. - Check the console output of the
EmailService
container to see the received message.
This example demonstrates a basic setup of asynchronous communication between microservices using RabbitMQ and Docker. In a real-world scenario, you would handle more complex scenarios, error handling, scalability, and ensure data integrity.
Please note that this example provides a foundation for understanding the communication pattern. Depending on your specific use case, you may need to consider additional aspects, such as message durability,