API Gateways in C#.NET?
Amir Doosti
Software Engineer | 20+ Years of Expertise | .NET, Industrial Automation with Beckhoff, Microservices Architecture
Microservices architecture has revolutionized the way we build and deploy applications. It offers flexibility, scalability, and agility, but it also brings challenges in terms of communication, security, and monitoring. Enter the API Gateway, a crucial component in the microservices world that simplifies these challenges. In this article, we'll delve into API Gateways, understand their significance, and explore how to implement one in a .NET ecosystem.
Sample Project
You will find a sample API Gateway in my GitHub that may help you to have a better understanding of how API Gateway works.
Due to the breadth of this topic, I will come back to it again in the future and examine its various parts such as authentication and authorization more comprehensively.
Understanding the Role of an API Gateway
An API Gateway serves as a central entry point for managing, securing, and routing incoming and outgoing requests in a microservices-based system.An API Gateway is an intermediary layer that stands between clients (such as web or mobile applications) and a collection of backend services. It functions as a reverse proxy that streamlines communication between clients and various microservices, providing several key benefits:
API Gateways are instrumental in managing the complexity of microservices and ensuring the security, performance, and reliability of your application's API layer. They have become a vital component in modern distributed systems, enabling developers to create resilient and scalable architectures.
Ocelot API Gateway
In the .NET ecosystem, you can implement an API Gateway using various tools and frameworks. One of the most popular options is to use Ocelot, an open-source API Gateway for .NET
It provides a rich set of features and configurations to effectively control and optimize the interactions between clients and microservices within a distributed system.
?You find the latest documentation for Ocelot in this link: https://ocelot.readthedocs.io/en/latest/?
Here is a list of most important features that is provided by Ocelot at the time of writing this article:
We already talked about some of them. Of course here I’m not going to discover all features of Ocelot but I’ll show you how to use Ocelot in .Net and configure the most important features of this API gateway.
Implementing an API Gateway in .NET
Let's go through the steps to create a basic API Gateway using Ocelot:
Step 1: Create a .NET Core Web Application
Start by creating a new .NET Core Web Application:
dotnet new web -n ApiGateway
Step 2: Install Ocelot NuGet Package
Add the Ocelot NuGet package to your project:
dotnet add package Ocelot
Step 3: Configuration
In your project, create a ocelot.json configuration file to define routing and other gateway settings.
Then add routing to ocelot.json.
Step 4: Configure the Service and Middleware
In your Program.cs file, configure Ocelot service and middleware:
First we need to read the ocelot.json and add it to the service:
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot(builder.Configuration);
And then add the ocelot middleware:
await app.UseOcelot();
Or
app.UseOcelot().Wait();
If it’s needed, you can configure Ocelot middleware like this example:
var config = new OcelotPipelineConfiguration
{
AuthorizationMiddleware =
async (downStreamContext, next) =>
??? ? await OcelotJwtMiddleware.CreateAuthorizationFilter(downStreamContext, next)
};
await app.UseOcelot(config);
Step 5: Running the API Gateway
Start your API Gateway application. It will listen on the defined port and route requests to the specified backend services based on the ocelot.json configuration.
Step 6: Test Your API Gateway
You can now test your API Gateway by making requests to it. For example, a request to https://localhost:5000/products will be routed to the productsservice backend service based on your configuration.
Configuring Ocelot
Routing
The primary function of Ocelot is forwarding input requests to the microservices behind the API gateway. So the client doesn’t need to know about underlying services and their addresses.
领英推荐
All requests come from Upstream (clients) and are redirected to Downstream (microservices).?
Ocelot is performing this job by using a configuration file which contains some Routes (an array of roots). Each route can define which upstream request pattern goes to which downstream address.
Look at this sample configuration:
{
"Routes": [
????{
??????"DownstreamPathTemplate": "/api/products/{prodId}",
??????"DownstreamScheme": "http",
??????"DownstreamHostAndPorts": [
????????{
??????????"Host": "productsservice",
??????????"Port": 80
????????}
??????],
??????"UpstreamPathTemplate": "/products/{prodId}",
??????"UpstreamHttpMethod": [ "Get" ]
????}
??]
}
?In this configuration, every request for getting a product like /products/10 with Get method, will redirect to a microservice with “productservice” host name at port 80 like this:
https://productservice:80/api/products/10
The rules for defining a route variable, constraints, etc. is similar to what we define in MapControllerRoute method in .Net
There are also lots of options that can help you to define routing as you need, like RouteIsCaseSensitive, Priority, UpstreamHttpMethod, UpstreamHttpMethod, UpstreamScheme, DownstreamScheme.
Load Balancer
Ocelot supports load balancing for downstream services. This means if you scale out downstream, Ocelot can work with it. Ocelot supports load balancing by distributing incoming requests across multiple instances of a microservice, thus improving system resilience. According to Ocelot documentation, there are four types of load balancer:?
Suppose you have two instances of a downstream service called service1 and service2.
Load balancing can be configured by specifying multiple host and port combinations in the "DownstreamHostAndPorts" section of a route. Ocelot will automatically distribute requests to these instances.
"DownstreamHostAndPorts": [
????{
????????"Host": "service1",
????????"Port": 80
????},
????{
????????"Host": "service2",
????????"Port": 80
????}
]
Authentication and Authorization
Authentication and authorization are critical aspects of securing an API Gateway like Ocelot. Ocelot provides a range of features and options to help you implement and enforce these security measures effectively. Here's a more detailed look at authentication and authorization in Ocelot:
Authentication in Ocelot
Authentication is the process of verifying the identity of a client making a request to an API Gateway. Ocelot supports multiple authentication mechanisms, including:
Authorization in Ocelot
Authorization determines whether an authenticated client has the necessary permissions to perform a specific action or access a particular resource. Ocelot offers several options for implementing authorization:
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityServer",
"AllowedScopes": [ "read", "write" ]
}
This configuration indicates that the IdentityServer authentication provider should be used for this route, and clients must have the read or write scope in their access token to access this route.
Notes on Secure Communication:
Ocelot is responsible for authentication and authorization at the API Gateway level. It's essential to secure communication between the API Gateway and the backend microservices as well. You should use secure protocols such as HTTPS to ensure the confidentiality and integrity of the data transmitted between the API Gateway and the services.
Authentication and authorization in Ocelot needs more explanation which I will cover in a separate article.
Rate Limiting
Ocelot supports rate limiting to control the number of requests to your microservices. You can define rate limiting policies and apply them to routes. Here's an example:
"RateLimitOptions": {
"ClientWhitelist": [],
"EnableRateLimiting": true,
"Period": "1s",
"PeriodTimespan": 1,
"Limit": 1
}
ClientWhitelist: The client in this array will not be affected by the rate limiting.
EnableRateLimiting: Enable/disable rate limit for an endpoint.
Period: If you make more requests than specified in the “Limit” field in this “Period” of time, Then the Rate Limit comes into play and you need to wait for “PeriodTimespan” to elapse before you make another request.
PeriodTimespan: If Rate Limit stops responding to the requests, the user needs to wait “PeriodTimespan” before responding enable.
Limit: This value specifies the maximum number of requests that a client can make in a defined period.
Conclusion
API Gateways are a fundamental component in microservices architectures, offering a centralized entry point for managing communication, security, and routing. In the .NET ecosystem, Ocelot provides a convenient way to implement an API Gateway, simplifying the complexities of microservices interactions. As your microservices ecosystem grows, an API Gateway becomes even more valuable, allowing you to maintain a cohesive and secure API surface for your clients while efficiently routing requests to the relevant services. It's a crucial tool for unlocking the full potential of microservices in your applications.
#microservice #design-pattern #api-gateway #dotnet