<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bernardo Costa Nascimento</title>
    <description>The latest articles on DEV Community by Bernardo Costa Nascimento (@bernas1104).</description>
    <link>https://dev.to/bernas1104</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F586334%2F8d1dc2a5-4586-4ab6-ba9d-0cf067cf0e18.jpeg</url>
      <title>DEV Community: Bernardo Costa Nascimento</title>
      <link>https://dev.to/bernas1104</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bernas1104"/>
    <language>en</language>
    <item>
      <title>The AI Craze</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Sat, 28 Feb 2026 19:31:32 +0000</pubDate>
      <link>https://dev.to/bernas1104/the-ai-craze-2164</link>
      <guid>https://dev.to/bernas1104/the-ai-craze-2164</guid>
      <description>&lt;p&gt;Lately I've been feeling really shitty about being a developer.&lt;/p&gt;

&lt;p&gt;I've always enjoyed tech and, once I got to university, I discovered how much joy programing gave (and, sometimes, a bit of hate).&lt;/p&gt;

&lt;p&gt;You could take some problem, think about it and create something, through your code, to resolve it. And, once you're were done, you felt great.&lt;/p&gt;

&lt;p&gt;Then, came "AI". Everybody started talking about. Every company started using it(and forcing us to use it as well). You open Twitter - yes, Twitter - and all you see is "how model XYZ is the new hotness". And, honestly? I'm kinda done.&lt;/p&gt;

&lt;p&gt;Don't get me wrong. I'm not writing this to tell you guys to "stop using AI". I use it most days. I think is a great tool to help you think about problems, do some boring tasks, provide boilerplate, etc... But I'm sick and tired of hearing people say that it is some kind of silver bullet and that all developers are cooked.&lt;/p&gt;

&lt;p&gt;You hear all these crazy stories about "how I used AI to vibe code my app and win 100k in a week", which, honestly, feels like bullshit, but, if it is such an amazing tool, why don't you hear stories about it crushing it at some legacy app?&lt;/p&gt;

&lt;p&gt;I don't use a lot of my time to read about AI stories, but, to this day, I've never seen a single story about an AI doing a good job on a legacy app.&lt;/p&gt;

&lt;p&gt;Also, every single day there is a story on Twitter about some vibe coded application that got its database exposed because some AI bro vibe coded the next greatest application.&lt;/p&gt;

&lt;p&gt;And, for me, this isn't even the worst part. As I said, I loved to think about and solve problems with code. And now? Am I supposed to love telling my AI agent(s) to spill some slop?&lt;/p&gt;

&lt;p&gt;I don't know, man... I've been feeling pretty shitty about my career as a dev lately. And, with each day, thinking if I should try to do something else... Not because "I'm cooked", but because I've lost the passion to do it. All thanks to AI.&lt;/p&gt;

&lt;p&gt;And you? What are your thoughts about the AI craze? Are you feeling hyped? down? Nothing changed? I'm curious...&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 6</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:44:45 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-6-2ico</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-6-2ico</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve?&lt;/li&gt;
&lt;li&gt;The Solution: Messaging&lt;/li&gt;
&lt;li&gt;Show Me the Code&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On part 5, we talked about &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-5-4j7i"&gt;Messaging&lt;/a&gt;. On the last part of this series, we'll talk about how to handle situations when services try to collaborate in a synchronous way, but are not able to: Circuit Breaker.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to solve? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As we said before, our application's services often need to collaborate. They can do this asynchronously, e.g. messaging, or they can do it synchronously. When they collaborate synchronously, the called service might be unavailable or with high latency. While the caller service waits for an answer, its resources, such as threads, will be blocked. This can lead to resource exhaustion, which would make the caller unavailable too. This can cascade on our entire application. So, how can we solve this?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Circuit Breaker &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We can introduce a Circuit Breaker on our services. Each service must implement a proxy, which will work similarly to an electrical circuit. If a call to an specific service fails too many times, the circuit breaker is activated and, for a period of time, all the following calls made to that service will fail automatically. After the period expires, the circuit breaker will allow some requests through. If none of them fail, the circuit breaker is deactivated. Otherwise, the timer will be reset.&lt;/p&gt;

&lt;p&gt;By failing fast, we'll avoid that the caller service hangs and wastes precious resources from a call that will, most likely, fail!&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Services can fail fast, avoiding the wasting of resources.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It's difficult to choose timeout values without creating false positives or adding excessive latency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show Me the Code &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Just for the sake of simplicity, I'll show you how to implement the Circuit Breaker pattern only on our API Gateway. If you want to dive deeper on the pattern and implement it between two services, you can head over to the &lt;a href="https://github.com/App-vNext/Polly"&gt;Polly project&lt;/a&gt; on Github. Polly is the same library Ocelot uses to implement their Circuit Breaker. Now, let's get to the code!&lt;/p&gt;

&lt;p&gt;To implement the Circuit Breaker on our API Gateway, we first need to add a package to the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Ocelot.Provider.Polly
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the Polly provider to our Gateway. After the installation, open the 'ocelot.json' file. As was the case with our Load Balancer, we'll need to apply our Circuit Breaker in a route per route basis. To do this, add the following to any route you want:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"QoSOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"ExceptionsAllowedBeforeBreaking"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"DurationOfBreak"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"TimeoutValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let me explain this code. "QoSOptions" stands for "Quality of Service Options", here will define our rules to activate the Circuit Breaker. The first property "ExceptionsAllowedBeforeBreaking" defines the number of times our calls can fail. The "DurationOfBreak" property defines how long the Circuit Breaker will remain active, in milliseconds. Finally, the "TimeoutValue" property defines how long a request can be left hanging without a response, also in milliseconds.&lt;/p&gt;

&lt;p&gt;We need to do one more thing to complete the setup: edit our "Startup.cs" file. We need to insert the Polly service to our Gateway:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Startp.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOcelot&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;AddConsul&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;AddPolly&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! We're finally done with our series. You now have a basic application that has an API Gateway with Load Balancing, uses a Service Registry with Health Checks to determine services' locations and availability dynamically, asynchronous communication with messaging, and can handle synchronous communication failure gracefully!&lt;/p&gt;

&lt;p&gt;Let me know what you think about this series on the comments below and, if you'd like to learn more about microservices, head over to &lt;a href="https://microservices.io/"&gt;microservices.io&lt;/a&gt;!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Microservices Patterns: Examples with Java - Chris Richardson&lt;/li&gt;
&lt;li&gt;Circuit Breaker pattern - &lt;a href="https://microservices.io/patterns/reliability/circuit-breaker.html"&gt;https://microservices.io/patterns/reliability/circuit-breaker.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Quality of Service - Ocelot -&lt;a href="https://ocelot.readthedocs.io/en/latest/features/qualityofservice.html"&gt;https://ocelot.readthedocs.io/en/latest/features/qualityofservice.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Polly - &lt;a href="https://github.com/App-vNext/Polly"&gt;https://github.com/App-vNext/Polly&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>csharp</category>
      <category>circuitbreaker</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 5</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:44:37 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-5-4j7i</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-5-4j7i</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve?&lt;/li&gt;
&lt;li&gt;The Solution: Messaging&lt;/li&gt;
&lt;li&gt;Show Me the Code&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On part 4, we discussed how to implement a &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-4-5he2"&gt;load balance&lt;/a&gt;. Now, we'll talk about one way that services can collaborate between each other. We'll talk about messaging.&lt;/p&gt;

&lt;p&gt;For this part of the series, I'll be using the code on my &lt;a href="https://github.com/bernas1104/ms-csharp-chapter"&gt;Github repository&lt;/a&gt; as a guide.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to solve? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When using the microservices architecture, services need to collaborate with each other. They can do this both synchronously and asynchronously.&lt;/p&gt;

&lt;p&gt;The synchronous communication is easy. We can, for example, call the REST API of another service. But how can we communicate asynchronously?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Messaging &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To communicate asynchronously, we need to use the messaging pattern. It implements asynchronous service communication, and can be done in a few ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Notifications - One service sends a message, but doesn't expect an answer and doesn't receive one;&lt;/li&gt;
&lt;li&gt;Request/Asynchronous Response - One service sends a message and awaits for a response that will come eventually;&lt;/li&gt;
&lt;li&gt;Publish/Subscribe - One service publishes a message to one or more services;&lt;/li&gt;
&lt;li&gt;Publish/Asynchronous Response - One service sends a message to one or more services, and awaits for responses that will come eventually.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefits of Messaging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Loosely runtime coupling since the sending service doesn't need to block, while waiting for a response;&lt;/li&gt;
&lt;li&gt;Better availability since the broker stores the messages in a buffer until a consumer is ready to process them;&lt;/li&gt;
&lt;li&gt;Support to a variety of communication patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks of Messaging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The broker is yet another component to keep track of;&lt;/li&gt;
&lt;li&gt;Since the communication is critical, the broker &lt;strong&gt;must&lt;/strong&gt; have a high availability.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Before the Code
&lt;/h3&gt;

&lt;p&gt;We need to quickly talk about two concepts: Aggregates and Domain Events. I won't go in much details about neither one, but these will be important for the messaging pattern and, specially, when deciding the set of services of your application.&lt;/p&gt;

&lt;h4&gt;
  
  
  Aggregates
&lt;/h4&gt;

&lt;p&gt;Chris Richardson defines as "a cluster of domain objects within a boundary that can be treated as a unit." Now, take my example application. It has a "User" domain object, right? The "User" only has a name and an e-mail address. Imagine that we'd like to store the user's home address. We could create a separate class for it, "Address", which would be a part of our "User" domain object.&lt;/p&gt;

&lt;p&gt;It doesn't make sense for us to work with the "Address" without its parent object, "User". So, we call our "Address" class a "Value Object". Our Aggregate, then, is composed of the domain object "User" and the value object "Address". We also can call the "User" class our Aggregate Root.&lt;/p&gt;

&lt;p&gt;Working with Aggregates makes our domain model easier to understand, since it groups multiple classes as a single entity. It also makes load, update and delete operations clearer. Finally, it helps us enforce invariants.&lt;/p&gt;

&lt;h4&gt;
  
  
  Domain Events
&lt;/h4&gt;

&lt;p&gt;Domain Events are very closely related to Aggregates. When something important happens to an Aggregate, e.g. a new Aggregate object is created, it might publish a Domain Event to anyone who might be interested.&lt;/p&gt;

&lt;p&gt;Here are a few reasons as to why Domain Events can be useful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintaining data consistency when using &lt;em&gt;sagas&lt;/em&gt; (another microservices pattern);&lt;/li&gt;
&lt;li&gt;Notifying a service that maintains a replica of the altered data (CQRS, another microservices pattern);&lt;/li&gt;
&lt;li&gt;Notifying another application;&lt;/li&gt;
&lt;li&gt;Sending user notifications;&lt;/li&gt;
&lt;li&gt;Monitoring to check if the application is working as intended;&lt;/li&gt;
&lt;li&gt;Analyzing events to model user behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are a few ways to identify domain events. They are usually defined by the application's requirements, but they can also be defined in a process called "event storming".&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me the Code &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we've talked about Aggregates and Domain Events, let's begin our implementation!&lt;/p&gt;

&lt;p&gt;As I said on the beginning, I'll use my example application here. The code contains: an API Gateway, two simple Web API projects and a docker compose file. The first Web API is a simple CRUD for a "User", which has a name and an e-mail. The second Web API doesn't do anything other than receiving messages and logging what was supposed to happen.&lt;/p&gt;

&lt;p&gt;Although the example on the repository is complete, I'll pretend as if it wasn't.&lt;/p&gt;

&lt;p&gt;Ok, let's begin. We'll first code our consumer's code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Consumer
&lt;/h3&gt;

&lt;p&gt;On the "Notification.API" folder (on the "notifications-api" project), we'll create a folder called "Consumers". Next, we'll create an "AbstractConsumer" class, which will hold the basic functionality of our messenger consumers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AbstractConsumer.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AbstractConsumer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;_serviceProvider&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;IConnection&lt;/span&gt; &lt;span class="n"&gt;_connection&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;IModel&lt;/span&gt; &lt;span class="n"&gt;_channel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_exchange&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_routingKey&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;AbstractConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;_serviceProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitializeEventBus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;NotImplementedException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;LogMessageReceived&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;SendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The properties "_connection", "Queue", "_channel", "_exchange" and "_routingKey" are all related to our messaging pattern, and I'll explain them in a moment. First, let's quickly go over the "_serviceProvider" property.&lt;/p&gt;

&lt;p&gt;We won't actually use it on our example, but if we were actually sending an e-mail to some user, we'd probably need an e-mail service. The "_serviceProvider" would be, then, used to retrieve an instance of our e-mail service to send that e-mail!&lt;/p&gt;

&lt;p&gt;Back to our messenger properties. They're all pretty self explanatory: "_connection" will provide our connection to the RabbitMQ server, "Queue" will hold the consumer's queue name, "_channel" will hold our RabbitMQ communication channel, "_exchange" will hold the name of the messenger exchange and, finally, "_routingKey" will hold the routing key of that consumer.&lt;/p&gt;

&lt;p&gt;The "InitializeEventBus" method will prepare our consumer to connect to the RabbitMQ server and, well, consume the messages that it's interested in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AbstractConsumer.cs&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;InitializeEventBus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connectionFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConnectionFactory&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;HostName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5672&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"your-user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"your-password"&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="n"&gt;_connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connectionFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"notifications-service-consumer"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;_channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExchangeDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ExchangeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;autoDelete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueueDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;exclusive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;autoDelete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueueBind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;_routingKey&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm not going to explain every argument of the called methods. If you want to better understand each of them, &lt;a href="https://www.rabbitmq.com/getstarted.html"&gt;take the RabbitMQ tutorial&lt;/a&gt;. It's pretty simple and will give you all the information you need!&lt;/p&gt;

&lt;p&gt;So, first we open a connection to our RabbitMQ server, then we open the communication channel. After that, we declare our exchange - if it doesn't exist already, it'll be created -, declare our queue - same effect as the exchange declaration - and, finally, we'll bind the queue to the exchange and define its routing key.&lt;/p&gt;

&lt;p&gt;Our exchange will act as a router, right? We can make every message go through a specific exchange and use a routing key to determine which queues will receive which messages. That way, the exchange will forward each message to its queue.&lt;/p&gt;

&lt;p&gt;Next, we need to &lt;em&gt;actually&lt;/em&gt; consume the messages. We'll implement our "ExecuteAsync" method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AbstractConsumer.cs&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;stoppingToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;EventingBasicConsumer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Received&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;contentArray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;contentString&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contentArray&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonConvert&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeserializeObject&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
                &lt;span class="n"&gt;contentString&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;SendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicAck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;eventArgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeliveryTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="n"&gt;_channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicConsume&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;autoAck&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;consumer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;consumer&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompletedTask&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our consumer's "ExecuteAsync" method will listen to our communication channel and define a callback function that will be executed when a new message is available. The callback will read the message as a byte array, which we'll use to deserialize it to our "T" object. With the message deserialized, we'll use its contents to send an e-mail and execute an ACK, so that the message can be deleted from the queue.&lt;/p&gt;

&lt;p&gt;Finally, we'll tell our channel what queue our consumer will be listening to and return the task as completed.&lt;/p&gt;

&lt;p&gt;We can, now, create specific consumers for our messages. In my example application, I created two consumers: UserCreated and UserUpdated. Both classes inherit from our AbstractConsumer class and we only need to implement the "SendEmail" method, which can be different to each class. For example, they can use different templates, so we can create a specific implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Producer
&lt;/h3&gt;

&lt;p&gt;Moving on to our Producer, i.e. the "users-api", we'll begin by creating our connection to the RabbitMQ server. On the "Infra" project, we'll create a folder called "MessageBus" and "RabbitMQClient" class, which implements the "IMessageBusClient" that defines the "Publish" method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// RabbitMQClient.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RabbitMQClient&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IMessageBusClient&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IConnection&lt;/span&gt; &lt;span class="n"&gt;_connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;RabbitMQClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;connectionFactory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConnectionFactory&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;HostName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;UserName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Password&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"123456"&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="n"&gt;_connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connectionFactory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"users-service-producer"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateModel&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonSerializerSettings&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;NullValueHandling&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;NullValueHandling&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ignore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;ContractResolver&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CamelCasePropertyNamesContractResolver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonConvert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SerializeObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Encoding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UTF8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExchangeDeclare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ExchangeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Topic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;durable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BasicPublish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;basicProperties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, this code is very similar to our Consumer's code. The basic difference is that we'll be taking a given object, serialize it, convert it to an array of bytes and publish it. We'll publish the message in a specified exchange, with a specific routing key.&lt;/p&gt;

&lt;p&gt;Moving on, we'll now apply the Aggregates and Domain Events concepts. We'll begin by creating an "AggregateRoot" class on our "Domain" project, on the "Entities" folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AggregateRoot.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AggregateRoot&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDomainEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_events&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDomainEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IDomainEvent&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Events&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_events&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;AddEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDomainEvent&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "AggregateRoot" will contain an array of "IDomainEvents" (Domain/Events/Interfaces), which is an empty interface that creates a common contract for our events. Our "User" class will inherit from the "AggregateRoot".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AggregateRoot&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to define a Domain Event:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// UserCreated.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserCreated&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IDomainEvent&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;FullName&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;FullName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;CreatedAt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the "UserCreated" domain event doesn't do much. It only stores the event information. So, how can we publish this? On our "UserService.cs" class, we'll inject our "RabbitMQClient". By doing this, we can access the publish method we created earlier.&lt;/p&gt;

&lt;p&gt;Now, when we create a user, we'll need a method that creates and adds the event to the array we defined earlier. After we ensure that the user was created on the database, we'll iterate over the events array and publish our message!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// User.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;NewGuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserCreated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// UserService.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UsersService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="n"&gt;IMessageBusClient&lt;/span&gt; &lt;span class="n"&gt;messageBus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="n"&gt;_messageBus&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;messageBus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;UserViewModel&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;CreateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserInputModel&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FullName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_usersRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"user-created"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="n"&gt;_messageBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;@event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;routingKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;exchange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"user-service"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! We've just created our "UserCreated" event and published it to our RabbitMQ server. If everything is right, we should be able to see on the RabbitMQ GUI that a message was, in fact, published and consumed. To make it even easier to see, you can add a "LogMessageReceived" method to your Consumer!&lt;/p&gt;

&lt;p&gt;We are almost done with the series. Next - and last - time, we'll be covering the &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-6-2ico"&gt;Circuit Breaker pattern&lt;/a&gt;. Until next time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Microservices Patterns: Examples with Java - Chris Richardson&lt;/li&gt;
&lt;li&gt;Messaging pattern - &lt;a href="https://microservices.io/patterns/communication-style/messaging.html"&gt;https://microservices.io/patterns/communication-style/messaging.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;RabbitMQ - Get Started - &lt;a href="https://www.rabbitmq.com/getstarted.html"&gt;https://www.rabbitmq.com/getstarted.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>csharp</category>
      <category>rabbitmq</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 4</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:44:28 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-4-5he2</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-4-5he2</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve?&lt;/li&gt;
&lt;li&gt;The Solution: Load Balancer&lt;/li&gt;
&lt;li&gt;Show Me the Code&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On part 3, we talked about &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13"&gt;Service Registry and Health Checks&lt;/a&gt;. Now, we're going to improve our Gateway and take advantage of the possibility of multiple instances given by the Service Registry.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to solve? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So far, we've implemented an API Gateway that receives all the requests and routes them accordingly. Also, our services/instances are registered with our Service Registry and the Gateway checks the service's location with it. But how can we make so that our Gateway uses all available instances of a service and no instance becomes overloaded?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Load Balancer &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To insure that, we need to implement a Load Balancer. This pattern will leverage the requests between available instances of our services. Ocelot gives us a simple way to implement a Load Balancer. Also, it provides a few different algorithms of load balancing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Round Robin - Imagine that you have three instances of a given service. The algorithm will make so that the first request is handled by instance #1, the second by instance #2, the third by instance #3, the fourth by #1 again, and so on;&lt;/li&gt;
&lt;li&gt;Least Connections - Every new request is sent to the instance with the least amount of active connections;&lt;/li&gt;
&lt;li&gt;Cookies Sticky Sessions - Uses a cookie to direct all request to a specific instance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: Keep in mind that other load balancing solutions might have different algorithms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show Me the Code &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To implement our Load Balancer, Ocelot makes it very easy. All we need to do is add a new property to our 'ocelot.json' file. This property needs to be added on a route per route basis:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"LoadBalancerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RoundRobin"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;..&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Our API Gateway can now balance the load between all of our services instances!&lt;/p&gt;

&lt;p&gt;On the next article, we'll talk about the &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-5-4j7i"&gt;Messaging pattern&lt;/a&gt; pattern. Until next time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Ocelot: Load Balancer - &lt;a href="https://ocelot.readthedocs.io/en/latest/features/loadbalancer.html#configuration"&gt;https://ocelot.readthedocs.io/en/latest/features/loadbalancer.html#configuration&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>ocelot</category>
      <category>csharp</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 3</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:44:19 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve?&lt;/li&gt;
&lt;li&gt;The solution: Service Registry &amp;amp; Health Checks&lt;/li&gt;
&lt;li&gt;
Show Me the Code

&lt;ul&gt;
&lt;li&gt;Service Registry&lt;/li&gt;
&lt;li&gt;Health Checks&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Last time we talked about &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-2-5bk4"&gt;API Gateways&lt;/a&gt;. Today, we'll talk about two patterns that are very closely related to Gateways and each other: Service Registry and Health Checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to solve? &lt;a&gt;
&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When we created our API Gateway, we had to manually define the location (host+port) of the service, right? But imagine the following scenario: a given service needs to be scaled in the X-Axis. The new instances will have different locations and they must be made dynamically available to the clients.&lt;/p&gt;

&lt;p&gt;Also, if one of our service instances becomes unavailable at any point, the Gateway must be aware that it can't route requests to that instance while it is unavailable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Service Registry &amp;amp; Health Checks &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;To solve our problems, we'll be using a combination of two patterns. First, let's discuss the Service Registry pattern.&lt;/p&gt;

&lt;p&gt;The Service Registry is, as the name suggests, another service on our ecosystem, that is responsible to register all the services/instances of our application, and keep track of their location. By doing that, our Gateway can, any time that a request arrives, check with the Registry and route the request accordingly. This makes it invisible to the client which instance will receive its request and, as the instances change, the Gateway can always know valid locations! This is known as &lt;em&gt;Server-side discovery&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2evpcwf3kg45koz4lx7y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2evpcwf3kg45koz4lx7y.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 1. Server-side discovery

 

&lt;p&gt;Also, since services must cooperate with each other, they, too, can access the Service Registry to find the location of another service instance. This is known as &lt;em&gt;Client-side discovery&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb8xpodvw6trbklvvrz5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhb8xpodvw6trbklvvrz5.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 2. Client-side discovery

 

&lt;h3&gt;
  
  
  Benefits of Service Registry
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Makes it possible to the API Gateway to discover all services'/instances' locations dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks of Service Registry
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Unless the Service Registry is part of the infrastructure, it's yet another component that must be installed, configured e maintained;&lt;/li&gt;
&lt;li&gt;Since the Service Registry is a critical part of the application, it &lt;strong&gt;must&lt;/strong&gt; have a high availability. If it becomes unavailable, the Gateway won't be able to router the requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But what if a registered instance becomes unavailable to receive requests? We shouldn't route anything to it, right? This is where our Health Checks pattern comes into play. As we register our services/instances, we'll also provide a way for the Service Registry to check if the registered instances are available to receive requests. If a instance is deemed 'unhealthy', our Gateway won't send any requests to it! That's awesome!&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Health Check
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It creates a way to check the health of the service/instance periodically.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks of Health Check
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The check might not be comprehensive enough or the instance might fail between health checks, making so that requests are routed to an unavailable service/instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Show Me the Code &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;So, let's begin with the code needed to implement our Service Registry, service registration and health checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Service Registry &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We'll begin by going the &lt;a href="https://consul.io/" rel="noopener noreferrer"&gt;Consul.io&lt;/a&gt; website and downloading it. Consul will act as our Service Registry. Just for the purposes of this tutorial, we'll be running Consul in developer mode. After downloading Consul, you can add it to you system PATH, or run it from wherever directory you want it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;consul agent &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our Service Registry, that's it. It's already running. You can check it by accessing &lt;a href="https://localhost:8500/" rel="noopener noreferrer"&gt;https://localhost:8500/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's move on to adjust our Gateway, so it'll check with our Registry for valid services/instances locations. We'll begin by editing our 'ocelot.json' file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DownstreamPathTemplate"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/v1/{everything}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DownstreamScheme"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"UpstreamPathTemplate"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/gateway/{everything}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"UpstreamHttpMethod"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PATCH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DELETE"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"ServiceName"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-SERVICE-NAME"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GlobalConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ServiceDiscoveryProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Consul"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we've eliminated the "DownstreamHostAndPorts" property and added the "ServiceName" property to our route. Then, we add the "ServiceDiscoveryProvider" property and gave it the host, port and type of our Service Discovery. To complete this setup, we need to add another package to our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Ocelot.Provider.Consul
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After it installs, just edit the "Startup.cs" file once again and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Startup.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOcelot&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;AddConsul&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it for our Gateway configuration. Now, we need to configure our services. They need to register with Consul, remember? That's what we'll do next.&lt;/p&gt;

&lt;p&gt;For any service you'd like to register, you must add the Consul package to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Consul
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we need to do a couple of things. First, we need to add some needed configuration to our "appsettings.json" (we could put the information directly to the code, but this is better).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"ConsulConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:8500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ServiceName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-SERVICE-NAME"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ServiceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"AN-UNIQUE-ID-FOR-EACH-INSTANCE"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: you must use the same "ServiceName" as you did on the routing in "ocelot.json" file. Also, the "ServiceId" is only needed if you plan to use multiple instances of the same service.&lt;/p&gt;

&lt;p&gt;After that, we need to add Consul registration as a service on our Web API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="nf"&gt;AddConsulConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IConsulClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConsulClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ConsulClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;consulConfig&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"ConsulConfig:Host"&lt;/span&gt;
            &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;consulConfig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the Consul client instance to our Web API. Now, we need to use the client instance to make our registration with Consul.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="nf"&gt;UseConsul&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;consulClient&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationServices&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IConsulClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationServices&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ILoggerFactory&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AppExtensions"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lifetime&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationServices&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IApplicationLifetime&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(!(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Properties&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"server.Features"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="n"&gt;FeatureCollection&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;addresses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IServerAddressesFeature&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Addresses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"address=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"ConsulConfig:ServiceName"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"ConsulConfig:ServiceId"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;registration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AgentServiceRegistration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Registering with Consul"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;consulClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ServiceDeregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;consulClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ServiceRegister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;lifetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ApplicationStopping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Register&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogInformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unregistering from Consul"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;consulClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ServiceDeregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAwait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above removes any previous instances registered with the same ID, registers our service/instance and, finally, tells our Web API that, when it shuts down, it should deregister our service/instance.&lt;/p&gt;

&lt;p&gt;And we're done! Now our services are registering with Consul and made available to our API Gateway. Let's begin to implement our health check!&lt;/p&gt;

&lt;h3&gt;
  
  
  Health Checks &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To add our health check, we first need to install the "AspNetCore.HealthChecks.System" package. This will add some basic health check features. If you need to check the connection to your database, you'll need another package. In my repository, I used PostgreSQL, so, in my case, I needed to add the "AspNetCore.HealthChecks.NpgSql" package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package AspNetCore.HealthChecks.System

dotnet add package AspNetCore.HealthChecks.NpgSql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the installation, we'll add the following code to our "ConfigureServices" method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Startup.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHealthChecks&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddProcessAllocatedMemoryHealthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="m"&gt;500&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"Process Memory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"self"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddPrivateMemoryHealthCheck&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="m"&gt;500&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="s"&gt;"Private memory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"self"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddNpgSql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetConnectionString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"DefaultConnection"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;"service"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've just added some checks for the amount of memory our Web API is consuming (the limit is 500MB for both "Process Memory" and "Private Memory"), and a check for our database connection.&lt;/p&gt;

&lt;p&gt;Finally, we need to create some endpoints to access this information. So, we'll add the following to our "Configure" method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Startup.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHealthChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HealthCheckOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;AllowCachingResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;ResponseWriter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UIResponseWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHealthCheckUIResponse&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseHealthChecks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"/ready"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HealthCheckOptions&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;AllowCachingResponses&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;Predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;ResponseWriter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UIResponseWriter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHealthCheckUIResponse&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've just added the endpoints "/health" and "/ready" to our Web API. Now, we need to tell our Service Registry that it should perform checks on the endpoints we've just created.&lt;/p&gt;

&lt;p&gt;Let's go back to our "UseConsul" method and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;registration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AgentServiceRegistration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Checks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AgentServiceCheck&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"ConsulConfig:ServiceName"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;HTTP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"https://&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AgentServiceCheck&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetValue&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="s"&gt;"ConsulConfig:ServiceName"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;HTTP&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;$"https://&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/ready"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Now our services can register and tell the Service Registry about their health checks. Consul will perform the checks every 30 seconds and, if the check fails, the service will be marked as 'unhealthy' and won't receive any requests until it resolve its problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IMPORTANT&lt;/strong&gt;: if your Consul instance can't perform the checks, try changing the 'https' to 'http' and the port to the 'http' port!&lt;/p&gt;

&lt;p&gt;The next topic of the series is &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-4-5he2"&gt;Load Balancer&lt;/a&gt;. Until next time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Microservices Patterns: Examples with Java - Chris Richardson&lt;/li&gt;
&lt;li&gt;Service registry pattern - &lt;a href="https://microservices.io/patterns/service-registry.html" rel="noopener noreferrer"&gt;https://microservices.io/patterns/service-registry.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Client-side service discovery pattern - &lt;a href="https://microservices.io/patterns/client-side-discovery.html" rel="noopener noreferrer"&gt;https://microservices.io/patterns/client-side-discovery.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Server-side service discovery pattern - &lt;a href="https://microservices.io/patterns/server-side-discovery.html" rel="noopener noreferrer"&gt;https://microservices.io/patterns/server-side-discovery.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Consul by HashiCorp - &lt;a href="https://www.consul.io/" rel="noopener noreferrer"&gt;https://www.consul.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Health Check - &lt;a href="https://microservices.io/patterns/observability/health-check-api.html" rel="noopener noreferrer"&gt;https://microservices.io/patterns/observability/health-check-api.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Health checks in ASP.NET Core - &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/health-checks?view=aspnetcore-5.0&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>csharp</category>
      <category>serviceregistry</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 2</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:44:08 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-2-5bk4</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-2-5bk4</guid>
      <description>&lt;h2&gt;
  
  
  Before we begin
&lt;/h2&gt;

&lt;p&gt;Before we start to talk about our topics, let's take a minute to understand how this will work.&lt;/p&gt;

&lt;p&gt;All articles will be divided into three parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve? - I'll give you a bit of context on what sort of problem that particular topic is trying to solve;&lt;/li&gt;
&lt;li&gt;The Solution: &lt;em&gt;topic name&lt;/em&gt; - I'll talk about the topic and how it'll solve those problems; and&lt;/li&gt;
&lt;li&gt;Show Me the Code - I'll go through a simple implementation of that topic and point you to some documentations, should you choose to dive deeper.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are we trying to solve?&lt;/li&gt;
&lt;li&gt;The solution: API Gateways&lt;/li&gt;
&lt;li&gt;Show Me the Code&lt;/li&gt;
&lt;li&gt;Bibliography&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Last time we discussed &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-1-18o9"&gt;what are microservices&lt;/a&gt;, but now it's time to apply some of its patterns. Today we'll learn about API Gateways!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are we trying to solve? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine this: you developed an online store that uses microservices. Now, you have a service that returns basic information about your products, another for product availability, another for reviews of products, and so on...&lt;br&gt;
Your front-end wants to access all this information, but it must know &lt;em&gt;ALL&lt;/em&gt; of the services addresses. For just a few services, it shouldn't be too hard, but imagine a scenario that your back-end has dozens or maybe hundreds of services. This would be a nightmare!&lt;/p&gt;

&lt;p&gt;There's also a few more reasons as to why gateways are important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The number of instances and their locations might change dynamically. The clients won't know the new address every time a new instance is started;&lt;/li&gt;
&lt;li&gt;Instances partitioning might change (Z-Axis scaling) and it should be invisible to your clients;&lt;/li&gt;
&lt;li&gt;Services might use a diverse set of protocols, and some of them might not be 'web friendly'.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, our problem is: How clients of a microservices architecture can access individual services in a simple way? By using &lt;em&gt;API Gateways&lt;/em&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  The solution: API Gateways &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Gateways act as a &lt;em&gt;Single Point of Entry&lt;/em&gt; to you application. All requests will go through the API Gateway and will be routed accordingly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22044ghbjpoh32nfwlbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F22044ghbjpoh32nfwlbr.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 1. API Gateway Pattern

 

&lt;p&gt;Instead of having a single API that fits all your clients' needs, your Gateway can expose a different API to each type of client. Better yet, you can have multiple API Gateways, one for each type of client! That's a variation of the pattern called &lt;em&gt;Back-Ends for Front-Ends&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6l5lrw9vhqwuh0d4cg7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6l5lrw9vhqwuh0d4cg7.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 2. API Gateway variation: Back-End for Front-Ends

 

&lt;p&gt;As we'll see in the next article, the Gateway will also have dynamically access to all instances and their address once we implement our &lt;em&gt;Service Registry&lt;/em&gt;, but let's not get ahead of ourselves.&lt;/p&gt;
&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;Let's list the benefits of using an API Gateway:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The client doesn't need to know how the application is partitioned between the services;&lt;/li&gt;
&lt;li&gt;The client doesn't need to know about the location (host+port) of the instances of the services;&lt;/li&gt;
&lt;li&gt;Provides the best API for each type of client;&lt;/li&gt;
&lt;li&gt;A single request to an API Gateway can retrieve data from multiple services;&lt;/li&gt;
&lt;li&gt;Simplifies the client by moving the logic of calling multiple services to the Gateway; and&lt;/li&gt;
&lt;li&gt;Translates a web protocol to any internal protocols that might be used.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;p&gt;There are also a couple of drawbacks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Increases the complexity, since the Gateway becomes another application that must be developed, deployed and maintained; and&lt;/li&gt;
&lt;li&gt;Increases the response time, as now all requests must make a new hop through the Gateway.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Show Me the Code &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we know what an API Gateway is, what it does, its benefits and drawbacks, let's implement a simple Gateway and see how it works.&lt;/p&gt;

&lt;p&gt;Start by creating two projects: one for the API Gateway and another for you Web API. Your Web API can be anything, right? If you need an idea just for this tutorial, you can head over to my &lt;a href="https://github.com/bernas1104/ms-csharp-chapter/" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;. There you'll also have access to a working example of this entire article series.&lt;/p&gt;

&lt;p&gt;Ok, now that you created you Web API, it's time to work on your API Gateway. Start by adding the &lt;a href="https://github.com/ThreeMammals/Ocelot" rel="noopener noreferrer"&gt;Ocelot&lt;/a&gt; package to your Gateway project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package Ocelot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the installation is complete, create a new JSON file on the project's root called 'ocelot.json'. Next, add the following lines to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DownstreamPathTemplate"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/v1/{everything}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DownstreamScheme"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"DownstreamHostAndPorts"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-LOCAL-PORT"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"UpstreamPathTemplate"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/api/gateway/{everything}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"UpstreamHttpMethod"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"POST"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PUT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PATCH"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DELETE"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"GlobalConfiguration"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's discuss the meaning of each line. Your Gateway, as said before, acts as a router for every request that comes through it. With that in mind, the "Routes" property is where we'll define every routing of our application.&lt;/p&gt;

&lt;p&gt;The properties "DownstreamPathTemplate", "DownstreamScheme" and "DownstreamHostAndPorts" define the format of the service routes, the used protocol and the base address respectively. Ocelot also uses some placeholders, e.g. "{everything}", to make it simple to define which routes will be available for each routing option.&lt;/p&gt;

&lt;p&gt;The properties "UpstreamPathTemplate" and "UpstreamHttpMethod" define the format of the address that will be available to the external world, and which HTTP methods your route will accept.&lt;/p&gt;

&lt;p&gt;So, with this JSON file, everytime someone tries to make a request to "&lt;a href="https://localhost:gateway_port/api/gateway/some-resource" rel="noopener noreferrer"&gt;https://localhost:gateway_port/api/gateway/some-resource&lt;/a&gt;", Ocelot will route the request to "&lt;a href="https://localhost:web_api_port/api/v1/some-resource" rel="noopener noreferrer"&gt;https://localhost:web_api_port/api/v1/some-resource&lt;/a&gt;". Cool, right?&lt;/p&gt;

&lt;p&gt;But we're not done yet. We need to configure our Gateway project to read the JSON file and use it to route requests. So, open your "Program.cs" file and edit the "CreateHostBuilder" method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Program.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IWebHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;WebHost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAppConfiguration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddJsonFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"ocelot.json"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UseStartup&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Startup&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The line "config.AddJsonFile("ocelot.json")" loads our Ocelot JSON Configuration to our Gateway. We're almost done! We just need to add Ocelot to our services. To do this, we'll edit our "Startup.cs" file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Startup.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddOcelot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IApplicationBuilder&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IWebHostEnvironment&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseOcelot&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;Wait&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we're done! You can start your Web API and your API Gateway and check the results!&lt;/p&gt;

&lt;p&gt;I'll wait for you on our next topic: &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13"&gt;Service Registry&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Microservices Patterns: With examples in Java - Chris Richardson&lt;/li&gt;
&lt;li&gt;API gateway pattern - &lt;a href="https://microservices.io/patterns/apigateway.html" rel="noopener noreferrer"&gt;https://microservices.io/patterns/apigateway.html&lt;/a&gt;
Ocelot Documentation - &lt;a href="https://ocelot.readthedocs.io/en/latest/index.html" rel="noopener noreferrer"&gt;https://ocelot.readthedocs.io/en/latest/index.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>csharp</category>
      <category>gateway</category>
    </item>
    <item>
      <title>An Introduction to Microservices pt. 1</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Tue, 24 Aug 2021 17:43:53 +0000</pubDate>
      <link>https://dev.to/bernas1104/an-introduction-to-microservices-pt-1-18o9</link>
      <guid>https://dev.to/bernas1104/an-introduction-to-microservices-pt-1-18o9</guid>
      <description>&lt;p&gt;Before we begin, I'd like to ask for a little bit of patience. I'm not a native English speaker, so, sorry for any errors in advance! I'll try my best s2.&lt;/p&gt;

&lt;p&gt;So, I recently made a presentation for my current workplace back-end developers chapter. The subject of the presentation, you guessed it: microservices architecture.&lt;/p&gt;

&lt;p&gt;As you can see from the diagram, microservices is a &lt;em&gt;really&lt;/em&gt; big topic!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplitw2ix06zd8ormsrui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplitw2ix06zd8ormsrui.png" alt="Microservices Patterns"&gt;&lt;/a&gt;&lt;/p&gt;
Figure 1. Microservices Patterns - microservices.io



&lt;p&gt;So, my idea is to create a mini series of articles to talk about the following microservices architecture patters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-2-5bk4"&gt;API Gateways&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-3-h13"&gt;Service Registry &amp;amp; Health Checks&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-4-5he2"&gt;Load Balancer&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-5-4j7i"&gt;Service communication: messaging&lt;/a&gt;; and&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-6-2ico"&gt;Circuit Breaker&lt;/a&gt;;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll be using ASP.NET Core to code the examples of these articles, but the ideas will remain the same no matter what language/framework you use, ok?&lt;/p&gt;

&lt;p&gt;Now, to be honest, I'd love to talk about more topics, but the truth is: I've just began to study microservices. For now, that's all I feel comfortable to talk about. But, you know, if enough people enjoy this mini series, I'll write about more topics, since I'll continue to study the architecture!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the microservices architecture?
&lt;/h2&gt;

&lt;p&gt;Before we dive into the topics, let's talk about what the microservices architecture actually is.&lt;/p&gt;

&lt;p&gt;We've all learned about monolithic architectures, right? That's what we're used to. An application that uses a monolithic architecture generates a single executable (for languages like Java, C#, Go, etc...), or has a single directory hierarchy (for languages like Ruby, JavaScript, etc...).&lt;/p&gt;

&lt;p&gt;Monolithic architecture aren't inherently bad, ok? It has some benefits, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Simple to develop -- IDEs and other tools are focused on building single applications;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Easier to apply radical changes -- You can change the code, the database scheme, build and deploy;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple to test -- Developers can write tests for the entire application (unit, integration, E2E...);&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple to scale -- You can run multiple instances of an application behind a load balancer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With all that said, why does development, testing, deploy and scaling start to become difficult as the monolithic application grows?&lt;/p&gt;

&lt;h3&gt;
  
  
  Monolithic Hell
&lt;/h3&gt;

&lt;p&gt;As time goes by, applications get bigger and more complex. Because of this, a series of problems start to happen.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Complexity: as said before, the code base of monolithic applications will grow as more and more features get added to the application. As a result, the code base becomes extremely complex, and no developer will fully understand all the code. This will make adding new feature and/or correcting new bugs more difficult and time consuming. By the end, any architectural style that was initially chose, will become a &lt;a href="https://en.wikipedia.org/wiki/Big_ball_of_mud" rel="noopener noreferrer"&gt;"big ball of mud"&lt;/a&gt;;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Slow Development: complexity aside, the size of the code base will also impact the IDE's responsiveness, build and startup times. This makes so that the edit-build-run-test loop takes a long time;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commits to Deploy: with several developers making commits to the same code base, the build will often be on an improper release state. &lt;br&gt;
If developers try to mitigate the problem by using a strategy like "feature/" branches, they will face a complicated merge process. Therefore, long periods of testing and stabilization will be necessary.&lt;br&gt;
Also, the testing process will be very complex. Since the code base is large and the impact of new changes is never clear, developers must run all tests in the CI. Some tests might even be manual. It's also complicated to diagnose and correct the cause of a failing test;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Difficulty to Scale&lt;br&gt;
In a big monolithic application, some modules might demand more memory, while others might demand more CPU power. Since all the modules belong in the same application, the server configuration might be compromised;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reliability&lt;br&gt;
It's very hard to fully test a big application. Therefore, bugs will find their way into production. To make things worse, it's difficult to isolate problems. For example, imagine a module has a memory leak, this could bring the entire application down;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Obsolete Stack&lt;br&gt;
As time goes by, the chosen stack might become obsolete. In a monolithic application is very hard to adopt new frameworks and technologies. To make the adoption, the team will have to re-write the entire application, which is very complicated and costly.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Microservices Save the Day
&lt;/h3&gt;

&lt;p&gt;With all the problems that surface with a big monolithic application, we need a solution. Enters: microservices architecture.&lt;/p&gt;

&lt;p&gt;The microservices architecture will impact on non-functional requirements, like: maintainability, testability, reliability...&lt;/p&gt;

&lt;p&gt;But what are microservices? Let's define it using Martin Abbot's and Michael Fisher's Scale Cube:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3m74f0211xbtj3df83i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd3m74f0211xbtj3df83i.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;
Fig 2. The Scale Cube



&lt;p&gt;As you can see, we can scale an application in three axis:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;X-Axis: that's when we create new instances of an application, and put them behind a load balancer to handle the increasing load;&lt;/li&gt;
&lt;li&gt;Z-Axis: that's when we partition the load between instances of an application. For example, instance #1 will handle usernames from A through H, instance #2 from I through P and instance #3 from R through Z;&lt;/li&gt;
&lt;li&gt;Y-Axis: this is the axis that defines microservices. Here, we'll use a process called 'functional decomposition' to break our monolithic application into services. Theses services can also be scaled in the X and Z-axis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'm not going to explain the 'functional decomposition' process for two reasons. First, as of yet, I don't know how the process works. I believe that the process is based on the Domain Driven Design (DDD), as you create sub-domain models for you application that define your services. And second, this article is just a simple introduction to microservices.&lt;/p&gt;

&lt;p&gt;So, a high-level definition for microservices is:&lt;/p&gt;

&lt;p&gt;"An architectural style that functionally decomposes an application into a set of services"&lt;br&gt;
-- Chris Richardson, Microservices Patterns.&lt;/p&gt;

&lt;h4&gt;
  
  
  Benefits
&lt;/h4&gt;

&lt;p&gt;The benefits of using a microservices architecture include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Enables continuous delivery and deployment of big and complex applications;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since the service is relatively small, automated tests are easier to write and faster to execute;&lt;/li&gt;
&lt;li&gt;Each service can be deployed independently of other services (if changes are local to the service). Therefore, it's easier to deploy new changes to production;&lt;/li&gt;
&lt;li&gt;Allows for teams to be autonomous and loosely coupled, as each team will be responsible, at most, for a few services. This makes development faster.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Services are "small" and easy to maintain;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With a smaller code base, the IDE's responsiveness is improved, the developers fully understand the service, and each service builds and starts faster, improving productivity;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Services scale independently;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As said before, each service can be scaled in the X and Z-axis as needed, and the servers can be better suited to each service's needs;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Easy experimentation and adoption of new technologies;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;As developers begin to code a new service, they are free to choose any technology/framework (to a certain degree, it will depend on the company's policy);&lt;/li&gt;
&lt;li&gt;Since the services are relatively small, re-write them using better solutions becomes more practical. If the new technology fails, you can just throw it away without risking the entire project;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Problem isolation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a service has a problem - e.g. memory leak - and it goes down, it won't bring down the entire application. Therefore, the impact is much smaller.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Drawbacks
&lt;/h4&gt;

&lt;p&gt;Ok, microservices have a lot of benefits, but what about the drawbacks? Nothing is perfect, right? Right! Microservices have some drawbacks too. Here a few:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It's difficult to determine the correct set of services;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There isn't a formula to determine the set of services. They must be carefully thought, otherwise you'll end up with a distributed monolith, which has the drawbacks of both microservices and monolithic architecture;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Distributed systems are more complex;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They need to communicate through some inter process communication mechanism, which are more complicated than simple method calls. They also need to deal with partial failures and high latency;&lt;/li&gt;
&lt;li&gt;Each service has it's own database, that makes it difficult to implement transactions and queries that might cover multiple services. They need to implement &lt;em&gt;sagas&lt;/em&gt; to maintain data consistency. Also, they can't recover data using simple queries, they need to implement API Composition or CQRS;&lt;/li&gt;
&lt;li&gt;It introduces the need for a high automation level;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Features that cover multiple services must be carefully deployed;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It's tough to decide when to adopt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consider, for example, a startup. They need to get their product to market ASAP, but microservices architecture is much more complex than building a simple monolithic application.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;As we saw, microservices have a lot of benefits and a few drawbacks - as anything does in tech. When you decide to adopt it, you must be very careful to implement it. But for complex applications, it's often the right tool for it.&lt;/p&gt;

&lt;p&gt;Now that we've talked about what microservices architecture is, we can begin talking about some of its patterns. On part two, we'll talk about &lt;a href="https://dev.to/bernas1104/an-introduction-to-microservices-pt-2-5bk4"&gt;API Gateways&lt;/a&gt;. Until next time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bibliography
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;What are microservices? - &lt;a href="https://microservices.io/" rel="noopener noreferrer"&gt;https://microservices.io/&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Microservices Patterns: With examples in Java - Chris Richardson;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Stoplight/Prism-CLI - Acelerando o desenvolvimento e aumentando a integração</title>
      <dc:creator>Bernardo Costa Nascimento</dc:creator>
      <pubDate>Thu, 25 Feb 2021 19:29:22 +0000</pubDate>
      <link>https://dev.to/devzwiz/stoplight-prism-cli-acelerando-o-desenvolvimento-e-aumentando-a-integracao-2ghp</link>
      <guid>https://dev.to/devzwiz/stoplight-prism-cli-acelerando-o-desenvolvimento-e-aumentando-a-integracao-2ghp</guid>
      <description>&lt;p&gt;Ao desenvolver novas APIs, muitas vezes os desenvolvedores (&lt;em&gt;devs&lt;/em&gt;) &lt;em&gt;front-end&lt;/em&gt; precisam &lt;em&gt;mockar&lt;/em&gt; dados para criar e demonstrar os &lt;em&gt;layouts&lt;/em&gt; que estão desenvolvendo. É uma atividade que demanda tempo e, eventualmente, o código será jogado fora. No &lt;em&gt;back-end&lt;/em&gt;, as &lt;em&gt;features&lt;/em&gt; podem demorar algum tempo para estarem disponíveis e, em caso de mudanças, o &lt;em&gt;dev&lt;/em&gt; terá de alterar o código, atualizar os testes, realizar uma nova build e um novo &lt;em&gt;deploy&lt;/em&gt;, atividades que demandam tempo. Como podemos otimizar as tarefas do &lt;em&gt;back-end&lt;/em&gt; e &lt;em&gt;front-end&lt;/em&gt; para que não haja código &lt;em&gt;mockado&lt;/em&gt; e novo ciclo de &lt;em&gt;dev-build-deploy&lt;/em&gt;? Podemos utilizar a ferramenta Stoplight/Prism-CLI.&lt;/p&gt;

&lt;p&gt;Prism permite que &lt;em&gt;devs&lt;/em&gt; criem &lt;em&gt;&lt;strong&gt;mocks&lt;/strong&gt;&lt;/em&gt; da API com uma base mínima de código no &lt;em&gt;back-end&lt;/em&gt;, fazendo com que não seja necessária a criação de &lt;em&gt;mocks&lt;/em&gt; – que serão, eventualmente, descartados – no &lt;em&gt;front-end&lt;/em&gt;. Ainda, torna possível testar o contrato da API, por meio de um &lt;em&gt;&lt;strong&gt;proxy&lt;/strong&gt;&lt;/em&gt;, auxiliando na diminuição de erros após mudanças no código. Por fim, como a ferramenta usa o OpenAPI como base para criação dos &lt;em&gt;mocks&lt;/em&gt; e &lt;em&gt;proxies&lt;/em&gt;, sua utilização auxilia na criação de documentações mais robustas para as APIs desenvolvidas. Este artigo abordará como utilizar a ferramenta em seus dois modos – &lt;em&gt;mock&lt;/em&gt; e &lt;em&gt;proxy&lt;/em&gt; – para auxiliar, acelerar e integrar o desenvolvimento &lt;em&gt;front-end&lt;/em&gt; e &lt;em&gt;back-end&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbh6zs1f1amp3ykh0w88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbh6zs1f1amp3ykh0w88.png" alt="Prism exemplo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Sumário
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Instalação do @stoplight/prism-cli&lt;/li&gt;
&lt;li&gt;Código &lt;em&gt;back-end&lt;/em&gt; &amp;amp; &lt;em&gt;OpenAPI Documentation&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Prism &lt;em&gt;Mock Server&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Prism &lt;em&gt;Proxy Server&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Conclusão&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Instalação do @stoplight/prism-cli
&lt;/h2&gt;

&lt;p&gt;Antes de mais nada, precisamos instalar a ferramenta Prism em nosso ambiente de desenvolvimento. A documentação prevê três formas de instalação, mas por motivos de simplicidade, abordaremos apenas o primeiro, que utiliza o NPM para realizar a instalação. Dessa forma, instale a ferramenta utilizando o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Usando NPM&lt;/span&gt;
npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @stoplight/prism-cli

&lt;span class="c"&gt;# Usando Yarn&lt;/span&gt;
yarn add global @stoplight/prism-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Código &lt;em&gt;back-end&lt;/em&gt; &amp;amp; &lt;em&gt;OpenAPI Documentation&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Com o Prism instalado, podemos iniciar o código &lt;em&gt;back-end&lt;/em&gt;. O &lt;a href="https://github.com/wizsolucoes/api-wiz-template" rel="noopener noreferrer"&gt;&lt;em&gt;template&lt;/em&gt; de APIs da Wiz&lt;/a&gt; já traz um exemplo básico de arquitetura de desenvolvimento de uma API e possui o OpenAPI instalado por &lt;em&gt;default&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;As rotas do &lt;em&gt;template&lt;/em&gt; possuem algumas &lt;em&gt;tags&lt;/em&gt; XML e &lt;em&gt;Annotations&lt;/em&gt;, que formarão o JSON responsável por gerar a documentação da API. Na Figura 1, a rota apresenta uma descrição (&lt;em&gt;summary&lt;/em&gt;), três códigos de resposta (&lt;em&gt;response&lt;/em&gt;) e três &lt;em&gt;schemas&lt;/em&gt; para os códigos de respostas gerados (&lt;em&gt;ProducesResponseType&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91wdeo6l9sw2p2s2iwpz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91wdeo6l9sw2p2s2iwpz.png" alt="Tags XML e Annotations para uma rota da API"&gt;&lt;/a&gt;&lt;br&gt;
Figura 1 - &lt;em&gt;Tags&lt;/em&gt; XML e &lt;em&gt;Annotations&lt;/em&gt; para uma rota da API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81tw2x1wcwaz1upjzykh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81tw2x1wcwaz1upjzykh.png" alt="Documentação gerada pelas tags XML e Annotations no código back-end"&gt;&lt;/a&gt;&lt;br&gt;
Figura 2 - Documentação gerada pelas &lt;em&gt;tags&lt;/em&gt; XML e &lt;em&gt;Annotations&lt;/em&gt; no código &lt;em&gt;back-end&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Se pararmos aqui, os exemplos de requisição e resposta, gerados pelo OpenAPI, serão genéricos, como visto na Figura 3.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyh0m2peqil8seq5chlpu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyh0m2peqil8seq5chlpu.png" alt="Exemplo de resposta genérica gerada pelo OpenAPI"&gt;&lt;/a&gt;&lt;br&gt;
Figura 3 - Exemplo de resposta genérica gerada pelo OpenAPI.&lt;/p&gt;

&lt;p&gt;O Prism é capaz de gerar informações aleatórias para compor as respostas, no entanto como veremos mais adiante, é possível ter maior controle sobre o conteúdo das respostas e, por consequência, definir exemplos que documentarão melhor a API em desenvolvimento.&lt;/p&gt;

&lt;p&gt;Para isso, adicionaremos &lt;em&gt;tags&lt;/em&gt; XML e &lt;em&gt;Annotations&lt;/em&gt; nas &lt;em&gt;ViewModels&lt;/em&gt; da API e, caso não existam &lt;em&gt;ViewModels&lt;/em&gt; específicas para erros, criaremos classes de exemplo para compor a documentação. A Figura 4 demonstra algumas das &lt;em&gt;tags&lt;/em&gt; e &lt;em&gt;Annotations&lt;/em&gt; utilizadas para melhor documentar a API. É importante ressaltar que, no caso da &lt;em&gt;Annotation&lt;/em&gt; &lt;em&gt;JsonSchemaExtensionData&lt;/em&gt;, é necessária a instalação do pacote &lt;em&gt;NjsonSchema.Annotations&lt;/em&gt;, que permite adicionar informações que não seriam identificadas pelo OpenAPI.&lt;/p&gt;

&lt;p&gt;Ao analisar a Figura 4, as &lt;em&gt;tags&lt;/em&gt; &lt;em&gt;example&lt;/em&gt; e &lt;em&gt;minimum&lt;/em&gt; provavelmente são familiares, pois estão previstas na especificação do OpenAPI. Mas e a &lt;em&gt;tag&lt;/em&gt; &lt;em&gt;x-faker&lt;/em&gt;?&lt;/p&gt;
&lt;h2&gt;
  
  
  Prism &lt;em&gt;Mock Server&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Como dito anteriormente, o Prism é capaz de gerar &lt;em&gt;mocks&lt;/em&gt; de respostas para as requisições feitas ao servidor gerado a partir da descrição do OpenAPI. Essas respostas podem ser estáticas ou dinâmicas. Vamos começar pelas respostas estáticas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgqqe3usa9d5mzsh7bnk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgqqe3usa9d5mzsh7bnk.png" alt="Exemplos de tags para documentação no OpenAPI"&gt;&lt;/a&gt;&lt;br&gt;
Figura 4 - Exemplos de &lt;em&gt;tags&lt;/em&gt; para documentação no OpenAPI.&lt;/p&gt;

&lt;p&gt;As respostas estáticas são produzidas a partir dos exemplos informados nas &lt;em&gt;ViewModels&lt;/em&gt; da API e serão o default ao iniciar o servidor por meio do comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prism mock http://localhost:5001/swagger/v1/swagger.json

&lt;span class="c"&gt;## Ou&lt;/span&gt;

prism mock path/to/descriptor.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ao iniciar o &lt;em&gt;mock&lt;/em&gt; server dessa maneira, todas as repostas serão baseadas nos exemplos fornecidos. Caso não haja um exemplo, o Prism gera respostas aleatórias com base nos tipos esperados.&lt;/p&gt;

&lt;p&gt;No entanto, a utilização das respostas estáticas pode gerar um viés no &lt;em&gt;front-end&lt;/em&gt;, uma vez que as respostas, em um cenário real, são variadas. Então, como podemos gerar respostas aleatórias, mas com algum controle sobre seu conteúdo? É aqui que a &lt;em&gt;tag&lt;/em&gt; &lt;em&gt;x-faker&lt;/em&gt; vai nos ajudar.&lt;/p&gt;

&lt;p&gt;Por baixo dos panos, o Prism utiliza a biblioteca Faker.js para gerar os dados de forma aleatória e, acessando a documentação da biblioteca, vemos que existem dezenas de métodos capazes de gerar respostas aleatórias para diversos contextos. Assim, podemos utilizar a &lt;em&gt;tag&lt;/em&gt; &lt;em&gt;x-faker&lt;/em&gt;, combinada com os métodos disponibilizados pela API, para imprimir contexto nas respostas. Na Figura 4, por exemplo, o “CEP” é gerado com base no método &lt;em&gt;&lt;strong&gt;address.zipCode&lt;/strong&gt;&lt;/em&gt; e, portanto, toda resposta não estática vai gerar um &lt;em&gt;zip code&lt;/em&gt; aleatório.&lt;/p&gt;

&lt;p&gt;Mas ainda fica uma dúvida: caso exista um exemplo, como o &lt;em&gt;mock&lt;/em&gt; server pode gerar respostas dinâmicas? Para isso, basta iniciar o &lt;em&gt;mock&lt;/em&gt; server com a &lt;em&gt;flag&lt;/em&gt; “-d” ou “--dynamic”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prism mock &lt;span class="nt"&gt;-d&lt;/span&gt; http://localhost:5001/swagger/v1/swagger.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ainda, é possível determinar que apenas uma rota específica gere respostas estáticas ou dinâmicas. Para isso, basta passar a utilizar o header “Prefer dynamic=true/false” em suas requisições. O mesmo header pode ser utilizado mais de uma vez e pode ajudar a controlar, também, o código da resposta gerada. Por exemplo, caso o &lt;em&gt;front-end&lt;/em&gt; queira testar um cenário de erro na resposta da API, ele pode criar uma requisição com contrato inválido (faltando um campo obrigatório, por exemplo) ou pode utilizar o header “Prefer code=400” para gerar uma resposta com código 400 (&lt;em&gt;Bad Request&lt;/em&gt;) por parte do &lt;em&gt;mock&lt;/em&gt; server. Para mais exemplos sobre o header, utilize a documentação do Prism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prism &lt;em&gt;Proxy Server&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Utilizando o &lt;em&gt;mock&lt;/em&gt; server, os &lt;em&gt;devs&lt;/em&gt; &lt;em&gt;front-end&lt;/em&gt; podem ir desenvolvendo os sites sem a necessidade de um &lt;em&gt;back-end&lt;/em&gt; funcional, sendo necessário trocar apenas o endereço base das requisições pelo endereço da API funcional, uma vez que esta esteja disponível (i.e. trocar &lt;a href="http://localhost:4010/api/vX/" rel="noopener noreferrer"&gt;http://localhost:4010/api/vX/&lt;/a&gt; por https://&amp;lt;projeto&amp;gt;-hml-api.azurewebsites.net/api/vX).&lt;/p&gt;

&lt;p&gt;Apesar disso, pequenas mudanças ou erros podem ter ocorrido – tanto no &lt;em&gt;front&lt;/em&gt;, quanto no &lt;em&gt;back&lt;/em&gt; – e as requisições ou os contratos não estarem de acordo com o esperado. Para testar os contratos, o Prism dispõe de um &lt;em&gt;proxy server&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;em&gt;proxy server&lt;/em&gt; utiliza um descritor do OpenAPI e o endereço da API para validar os contratos de requisição e resposta. Dessa maneira, o usuário pode realizar chamadas à API e verificar se todas as requisições feitas e as respostas geradas batem com o que está definido no descritor, garantido que, uma vez que a API vá para produção, &lt;em&gt;front&lt;/em&gt; e &lt;em&gt;back&lt;/em&gt; não possuam erros de contrato. O &lt;em&gt;proxy server&lt;/em&gt; pode ser iniciado pelo comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prism proxy path/to/descriptor.json https://&amp;lt;projeto&amp;gt;-hml-api.azurewebsites.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para mais informações sobre o &lt;em&gt;proxy server&lt;/em&gt;, acesse a documentação do Prism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;A ferramenta Prism server para auxiliar a abordagem “&lt;em&gt;design-first&lt;/em&gt;” para o desenvolvimento de APIs por meio do &lt;em&gt;mock&lt;/em&gt; e, uma vez que todas as informações e preparativos estejam nas mãos do time de &lt;em&gt;back-end&lt;/em&gt;, o proxy permite testar os contratos criados entre &lt;em&gt;front&lt;/em&gt; e &lt;em&gt;back&lt;/em&gt;.&lt;br&gt;
    Sendo assim, o Prism pode auxiliar na integração entre &lt;em&gt;devs&lt;/em&gt; &lt;em&gt;front&lt;/em&gt; e &lt;em&gt;back&lt;/em&gt;, que terão de chegar a um consenso sobre os contratos, permite que o front desenvolva sem a necessidade de uma API e auxilia o &lt;em&gt;back&lt;/em&gt; em uma melhor documentação da API em desenvolvimento.&lt;/p&gt;

</description>
      <category>api</category>
      <category>documentation</category>
      <category>frontend</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
