Dapr in a microservices architecture

Premier Developer

Premier

Application Development Manager Erick Ramirez introduces dapr and provides a walkthrough of using it to create an ASP.NET Core web application.


Dapr is an event driven runtime that helps to build stateless and stateful microservice applications, with a diversity of languages and frameworks. It is still in alpha version, which is not yet recommended for production environments but this will be very helpful for developers in the near feature.

One of the main patterns you should consider when designing a microservices architecture is publisher – subscriber, and Dapr provides support for this pattern. This pattern consists of a message broker where event consumers and producers are decoupled from one another and communicate by sending and receiving messages associated with a namespace. Using dapr we are going to have an “At-least-Once messaging guarantee”. This means that a message is delivered at least once to any subscriber when the response status code is 200 or returns no error. Dapr will deliver the message to only one instance, if more than one exists.

To install and configure Dapr, you can use the following guide Getting Started – Environment Setup. Standalone mode was used for this article, but a guide to install it in a Kubernetes cluster is also available.

To demonstrate this, we described the following scenario:

Before we start typing code, we need to reference the Nuget package Dapr.AspNetCore (this is preview only – v0.4.0-preview01)

Next, we initialize the subscriber Handler that will create an endpoint to dapr/subscribe that returns the topics. Following this, we must register the CloudEvents middleware to receive every incoming request with the content type of “application/cloudevents+json”

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   if (env.IsDevelopment())
   {
      app.UseDeveloperExceptionPage();
   }
   app.UseCloudEvents();
   app.UseRouting();
   app.UseAuthorization();
   app.UseEndpoints(endpoints =>
   {
      endpoints.MapSubscribeHandler();
      endpoints.MapControllers();
      }
   );
}

Once that we have created the project, we need to add the first MessageController, where we initialize the logger in the constructor, and add a new method that will receive all messages from the queue, as you can see in the code snippet:

[ApiController]
public class MessageController : ControllerBase
{
   private readonly ILogger<MessageController> _logger;
   public MessageController(ILogger<MessageController> logger)
   {
      _logger = logger;
   }

   [HttpPost]
   [Route("api/message")]
   public async Task<IActionResult> ReceiveMessage([FromBody]Message message)
   {
      _logger.LogInformation($"Message with id {message.Id.ToString()} received!");

      //Validate message received
      using (var httpClient = new HttpClient())
      {
         var result = await httpClient.PostAsync(
            "http://localhost:3500/v1.0/publish/messagetopic",
            new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, "application/json")
            );

         _logger.LogInformation($"Message with id {message.Id.ToString()} published with status {result.StatusCode}!");
      }

      return Ok();
   }

Next, we add a new operation named “ProcessMessage” to process all the messages that will be receiving.

   [Topic("messagetopic")]
   [HttpPost]
   [Route("messagetopic")]
   public async Task<IActionResult> ProcessOrder([FromBody]Message message)
   {
      //Process message placeholder
      _logger.LogInformation($"Message with id {message.Id.ToString()} processed!");
      return Ok();
   }

Finally, we create a new POCO to store the Message properties, as it shown in the following code snippet:

   public class Message
   {
      public Guid Id { get; set; }
      public string Content { get; set; }
      public string Subject { get; set; }
   }
}

Once everything is in place, we need to initialize dapr with the following command:

dapr init

Next, we start the ASP.NET Core application, listening on HTTP port 5000, and dapr on port 3500:

dapr run --app-id pubsub --app-port 5000 --port 3500 dotnet run

Now that our application is running, let’s see how this works. First, we will open a new Postman window and create a request. We will perform a new HTTP GET operation to the following URL http://localhost:5000/dapr/subscribe

We receive the topics that we are subscribed to as a result. Then, we will create a new request with HTTP POST to invoke the ProcessMessage method with the following payload:

Analyzing the command window output, we can see that the message was received, published, and processed successfully.

You can select a broker like Redis, RabitMQ, Azure Service Bus, etc. to establish the pub/sub component.

Dapr also supports following features through HTTP/gRPC to implement the sidecar pattern:

  • Service to service invocation
  • State management
  • Publish and subscribe
  • Resource bindings & triggers
  • Actor runtime
  • Distributed tracing

If you need further assistance you can contact Microsoft Developer Support Services.

0 comments

Leave a comment