{"id":38524,"date":"2020-03-04T06:00:43","date_gmt":"2020-03-04T13:00:43","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/premier-developer\/?p=38524"},"modified":"2020-03-03T14:13:30","modified_gmt":"2020-03-03T21:13:30","slug":"dapr-in-a-microservices-architecture","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/dapr-in-a-microservices-architecture\/","title":{"rendered":"Dapr in a microservices architecture"},"content":{"rendered":"<p>Application Development Manager <a href=\"https:\/\/www.linkedin.com\/in\/erick-daniel-ramirez-b5911041\/\">Erick Ramirez<\/a> introduces dapr and provides a walkthrough of using it to create an ASP.NET Core web application.<\/p>\n<hr \/>\n<p>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.<\/p>\n<p>One of the main patterns you should consider when designing a microservices architecture is publisher \u2013 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 \u201cAt-least-Once messaging guarantee\u201d. 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.<\/p>\n<p>To install and configure Dapr, you can use the following guide <a href=\"https:\/\/github.com\/dapr\/docs\/blob\/master\/getting-started\/environment-setup.md\">Getting Started \u2013 Environment Setup<\/a>. Standalone mode was used for this article, but a guide to install it in a Kubernetes cluster is also available.<\/p>\n<p>To demonstrate this, we described the following scenario:<\/p>\n<p><img decoding=\"async\" width=\"724\" height=\"422\" class=\"wp-image-38532\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-17.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-17.png 724w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-17-300x175.png 300w\" sizes=\"(max-width: 724px) 100vw, 724px\" \/><\/p>\n<p><img decoding=\"async\" width=\"974\" height=\"621\" class=\"wp-image-38534\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-19.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-19.png 974w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-19-300x191.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-19-768x490.png 768w\" sizes=\"(max-width: 974px) 100vw, 974px\" \/><\/p>\n<p>Before we start typing code, we need to reference the Nuget package Dapr.AspNetCore (this is preview only \u2013 v0.4.0-preview01)<\/p>\n<p><img decoding=\"async\" width=\"1163\" height=\"76\" class=\"wp-image-38535\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-20.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-20.png 1163w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-20-300x20.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-20-1024x67.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-20-768x50.png 768w\" sizes=\"(max-width: 1163px) 100vw, 1163px\" \/><\/p>\n<p>Next, we initialize the subscriber Handler that will create an endpoint to dapr\/subscribe that returns the topics. Following this, we must register the <em>CloudEvents<\/em> middleware to receive every incoming request with the content type of \u201capplication\/cloudevents+json\u201d<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Sample code\">public void Configure(IApplicationBuilder app, IWebHostEnvironment env)\r\n{\r\n   if (env.IsDevelopment())\r\n   {\r\n      app.UseDeveloperExceptionPage();\r\n   }\r\n   app.UseCloudEvents();\r\n   app.UseRouting();\r\n   app.UseAuthorization();\r\n   app.UseEndpoints(endpoints =&gt;\r\n   {\r\n      endpoints.MapSubscribeHandler();\r\n      endpoints.MapControllers();\r\n      }\r\n   );\r\n}<\/pre>\n<p><span style=\"font-size: 1rem;\">Once that we have created the project, we need to add the first <\/span><em style=\"font-size: 1rem;\">MessageController<\/em><span style=\"font-size: 1rem;\">, 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:<\/span><\/p>\n<pre class=\"lang:c# decode:true\" title=\"Sample code\">[ApiController]\r\npublic class MessageController : ControllerBase\r\n{\r\n   private readonly ILogger&lt;MessageController&gt; _logger;\r\n   public MessageController(ILogger&lt;MessageController&gt; logger)\r\n   {\r\n      _logger = logger;\r\n   }\r\n\r\n   [HttpPost]\r\n   [Route(\"api\/message\")]\r\n   public async Task&lt;IActionResult&gt; ReceiveMessage([FromBody]Message message)\r\n   {\r\n      _logger.LogInformation($\"Message with id {message.Id.ToString()} received!\");\r\n\r\n      \/\/Validate message received\r\n      using (var httpClient = new HttpClient())\r\n      {\r\n         var result = await httpClient.PostAsync(\r\n            \"http:\/\/localhost:3500\/v1.0\/publish\/messagetopic\",\r\n            new StringContent(JsonConvert.SerializeObject(message), Encoding.UTF8, \"application\/json\")\r\n            );\r\n\r\n         _logger.LogInformation($\"Message with id {message.Id.ToString()} published with status {result.StatusCode}!\");\r\n      }\r\n\r\n      return Ok();\r\n   }<\/pre>\n<p><span style=\"font-size: 1rem;\">Next, we add a new operation named \u201cProcessMessage\u201d to process all the messages that will be receiving.<\/span><\/p>\n<pre class=\"lang:c# decode:true\" title=\"Sample code\">   [Topic(\"messagetopic\")]\r\n   [HttpPost]\r\n   [Route(\"messagetopic\")]\r\n   public async Task&lt;IActionResult&gt; ProcessOrder([FromBody]Message message)\r\n   {\r\n      \/\/Process message placeholder\r\n      _logger.LogInformation($\"Message with id {message.Id.ToString()} processed!\");\r\n      return Ok();\r\n   }<\/pre>\n<p>Finally, we create a new POCO to store the <em>Message<\/em> properties, as it shown in the following code snippet:<\/p>\n<pre class=\"lang:c# decode:true \" title=\"Sample code\">   public class Message\r\n   {\r\n      public Guid Id { get; set; }\r\n      public string Content { get; set; }\r\n      public string Subject { get; set; }\r\n   }\r\n}<\/pre>\n<p><span style=\"font-size: 1rem;\">Once everything is in place, we need to initialize dapr with the following command:<\/span><\/p>\n<pre class=\"lang:ps decode:true \">dapr init<\/pre>\n<p><img decoding=\"async\" width=\"639\" height=\"99\" class=\"wp-image-38536\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-21.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-21.png 639w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-21-300x46.png 300w\" sizes=\"(max-width: 639px) 100vw, 639px\" \/><\/p>\n<p>Next, we start the ASP.NET Core application, listening on HTTP port 5000, and dapr on port 3500:<\/p>\n<pre class=\"lang:ps decode:true \">dapr run --app-id pubsub --app-port 5000 --port 3500 dotnet run<\/pre>\n<p><img decoding=\"async\" width=\"1448\" height=\"707\" class=\"wp-image-38537\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-22.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-22.png 1448w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-22-300x146.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-22-1024x500.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-22-768x375.png 768w\" sizes=\"(max-width: 1448px) 100vw, 1448px\" \/><\/p>\n<p>Now that our application is running, let\u2019s 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 <a href=\"http:\/\/localhost:5000\/dapr\/subscribe\">http:\/\/localhost:5000\/dapr\/subscribe<\/a><\/p>\n<p><img decoding=\"async\" width=\"1513\" height=\"348\" class=\"wp-image-38538\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-23.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-23.png 1513w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-23-300x69.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-23-1024x236.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-23-768x177.png 768w\" sizes=\"(max-width: 1513px) 100vw, 1513px\" \/><\/p>\n<p>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 <em>ProcessMessage<\/em> method with the following payload:<\/p>\n<p><img decoding=\"async\" width=\"1495\" height=\"383\" class=\"wp-image-38539\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-24.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-24.png 1495w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-24-300x77.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-24-1024x262.png 1024w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-24-768x197.png 768w\" sizes=\"(max-width: 1495px) 100vw, 1495px\" \/><\/p>\n<p>Analyzing the command window output, we can see that the message was received, published, and processed successfully.<\/p>\n<p><img decoding=\"async\" width=\"963\" height=\"138\" class=\"wp-image-38540\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-25.png\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-25.png 963w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-25-300x43.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2020\/02\/word-image-25-768x110.png 768w\" sizes=\"(max-width: 963px) 100vw, 963px\" \/><\/p>\n<p>You can select a broker like Redis, RabitMQ, Azure Service Bus, etc. to establish the pub\/sub component.<\/p>\n<p>Dapr also supports following features through HTTP\/gRPC to implement the sidecar pattern:<\/p>\n<ul>\n<li>Service to service invocation<\/li>\n<li>State management<\/li>\n<li>Publish and subscribe<\/li>\n<li>Resource bindings &amp; triggers<\/li>\n<li>Actor runtime<\/li>\n<li>Distributed tracing<\/li>\n<\/ul>\n<p>If you need further assistance you can contact Microsoft Developer Support Services.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Dapr is an event driven runtime that helps to build stateless and stateful microservice applications, with a diversity of languages and frameworks.<\/p>\n","protected":false},"author":582,"featured_media":37933,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9027,1],"tags":[62,3],"class_list":["post-38524","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microservices","category-permierdev","tag-microservices","tag-team"],"acf":[],"blog_post_summary":"<p>Dapr is an event driven runtime that helps to build stateless and stateful microservice applications, with a diversity of languages and frameworks.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/38524","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=38524"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/38524\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/37933"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=38524"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=38524"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=38524"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}