Event Broker Implementation in C# Using Azure Service Bus

event-broker-implementation-in-c#-using-azure-service-bus

Hi devs

The Event Broker Pattern is an essential part of modern distributed systems, particularly for microservices. It serves as a mediator for communication between producers and consumers of events, ensuring decoupled and scalable systems.

In this post, we’ll implement the Event Broker Pattern using Azure Service Bus in a practical example involving an Order Service, Inventory Service, and Payment Service.

What Is an Event Broker?

An Event Broker is a centralized system that manages the routing of events from producers to consumers. Instead of services directly communicating with each other, they publish or subscribe to events via the broker.

In our implementation, the Azure Service Bus Topic acts as the Event Broker, managing the following:

  • Routing events to multiple subscribers.
  • Decoupling services, as they don’t need to know about each other.
  • Ensuring reliable delivery of messages.

How the Event Broker Works

In this example:

  1. Order Service acts as the event producer, publishing an event (OrderPlaced).
  2. Azure Service Bus acts as the event broker, routing events to subscribers.
  3. Inventory Service and Payment Service are the event consumers, processing the OrderPlaced event.

This architecture ensures scalability, as new consumers can be added without modifying the producer.

Step-by-Step Implementation

Here’s how to set up and implement the pattern.

Step 1: Prerequisites

  1. Azure Setup:

    • Create a Service Bus Namespace in the Azure Portal.
    • Add a Topic named OrdersTopic.
    • Add Subscriptions: InventorySubscription and PaymentSubscription.
  2. Development Setup:

    • Create a new .NET project:
     dotnet new console -n EventBrokerExample
    
  • Install the Azure.Messaging.ServiceBus package:

     dotnet add package Azure.Messaging.ServiceBus
    

Step 2: Define a Shared Order Model

public class Order
{
    public int Id { get; set; }
    public int ProductId { get; set; }
    public int Quantity { get; set; }
    public decimal TotalPrice { get; set; }
}

This model will represent the data passed between the services.

Step 3: Implement the Event Producer (Order Service)

The Order Service publishes events to the Azure Service Bus Topic.

using Azure.Messaging.ServiceBus;
using System.Text.Json;

public class OrderPublisher
{
    private readonly ServiceBusSender _sender;

    public OrderPublisher(string connectionString, string topicName)
    {
        var client = new ServiceBusClient(connectionString);
        _sender = client.CreateSender(topicName);
    }

    public async Task PublishOrderPlacedEventAsync(Order order)
    {
        var message = new ServiceBusMessage(JsonSerializer.Serialize(order))
        {
            Subject = "OrderPlaced"
        };
        await _sender.SendMessageAsync(message);
        Console.WriteLine($"Published OrderPlaced event for Order ID: {order.Id}");
    }
}

// Usage:
var connectionString = "";
var topicName = "OrdersTopic";

var publisher = new OrderPublisher(connectionString, topicName);
var order = new Order { Id = 1, ProductId = 101, Quantity = 2, TotalPrice = 50.00m };
await publisher.PublishOrderPlacedEventAsync(order);

This sends an event to the Event Broker (Service Bus Topic).

Step 4: Implement the Event Consumers

Inventory Service

The Inventory Service subscribes to the OrderPlaced event and updates stock.

using Azure.Messaging.ServiceBus;
using System.Text.Json;

public class InventoryService
{
    private readonly ServiceBusProcessor _processor;

    public InventoryService(string connectionString, string topicName, string subscriptionName)
    {
        var client = new ServiceBusClient(connectionString);
        _processor = client.CreateProcessor(topicName, subscriptionName, new ServiceBusProcessorOptions());
    }

    public void Start()
    {
        _processor.ProcessMessageAsync += OnMessageReceived;
        _processor.ProcessErrorAsync += OnError;
        _processor.StartProcessingAsync();
    }

    private async Task OnMessageReceived(ProcessMessageEventArgs args)
    {
        var order = JsonSerializer.Deserialize<Order>(args.Message.Body.ToString());
        Console.WriteLine($"InventoryService processing Order ID: {order.Id}");
        Console.WriteLine($"Reducing stock for Product ID: {order.ProductId}");
        await args.CompleteMessageAsync(args.Message);
    }

    private Task OnError(ProcessErrorEventArgs args)
    {
        Console.WriteLine($"Error: {args.Exception.Message}");
        return Task.CompletedTask;
    }
}

// Usage:
var inventoryService = new InventoryService("", "OrdersTopic", "InventorySubscription");
inventoryService.Start();

Payment Service

The Payment Service processes the payment for the order.

using Azure.Messaging.ServiceBus;
using System.Text.Json;

public class PaymentService
{
    private readonly ServiceBusProcessor _processor;

    public PaymentService(string connectionString, string topicName, string subscriptionName)
    {
        var client = new ServiceBusClient(connectionString);
        _processor = client.CreateProcessor(topicName, subscriptionName, new ServiceBusProcessorOptions());
    }

    public void Start()
    {
        _processor.ProcessMessageAsync += OnMessageReceived;
        _processor.ProcessErrorAsync += OnError;
        _processor.StartProcessingAsync();
    }

    private async Task OnMessageReceived(ProcessMessageEventArgs args)
    {
        var order = JsonSerializer.Deserialize<Order>(args.Message.Body.ToString());
        Console.WriteLine($"PaymentService processing Order ID: {order.Id}");
        Console.WriteLine($"Processing payment of {order.TotalPrice:C}");
        await args.CompleteMessageAsync(args.Message);
    }

    private Task OnError(ProcessErrorEventArgs args)
    {
        Console.WriteLine($"Error: {args.Exception.Message}");
        return Task.CompletedTask;
    }
}

// Usage:
var paymentService = new PaymentService("", "OrdersTopic", "PaymentSubscription");
paymentService.Start();

How It All Works

  1. Order Service publishes an OrderPlaced event to the Service Bus Topic.
  2. Azure Service Bus (Event Broker) forwards the event to all subscribers.
  3. Inventory Service updates the stock.
  4. Payment Service processes the payment.

Benefits of This Approach

  1. Decoupling: Each service is independent and doesn’t directly call others.
  2. Scalability: Multiple consumers can process events concurrently.
  3. Flexibility: Adding new consumers requires no changes to existing producers.
  4. Reliability: Azure Service Bus ensures message delivery with retries.

Conclusion

The Event Broker Pattern simplifies communication between microservices, making systems more scalable and maintainable. Using Azure Service Bus makes it even easier to implement this architecture with minimal effort.

Keep coding 🙂

Total
0
Shares
Leave a Reply

Your email address will not be published. Required fields are marked *

Previous Post
sunday-rewind:-show-your-true-innovative-colours-by-julia-shalet

Sunday Rewind: Show your true innovative colours by Julia Shalet

Next Post
angular-19-is-here,-next.js-from-china,-newest-javascript-engine-and-more

Angular 19 is Here, Next.js From China, NEWEST JavaScript Engine and more

Related Posts

AI治理最重要的能力:缺乏证据支持时懂得暂停

1)观点先行(P0) 一句话观点: 在 AI 协作里,最有价值的治理能力不是“更快修完”,而是“证据不够时敢停下,并把缺什么证据说清楚”。 2)治理背景(P1) 复杂系统里的真实问题,不是没人干活,而是大家都在干活,却很难判断到底有没有真的完成。 AI 参与后,这个问题会更明显: AI 很容易给出“看起来已经完成”的答案。 多个智能体并行提交回执,信息会很快变成噪音。 模块测试通过,常常被误读成系统已经恢复。 本地治理体系之所以更快,不是因为流程更短,而是因为它把“没完成”这件事制度化了: 可以停在中间状态。 可以明确写出阻断原因。 可以等证据补齐后再推进状态。 3)信号提取(P0)…
Read More