Service Discovery in Microservices with C# and .NET
Amir Doosti
Software Engineer | 20+ Years of Expertise | .NET, Industrial Automation with Beckhoff, Microservices Architecture
Microservices architecture has revolutionized the way we design and build software systems, allowing us to break down complex applications into smaller, independently deployable services. However, managing these services and ensuring they can find and communicate with each other can be a daunting task. This is where the Service Discovery pattern comes into play.
In this article, we'll explore the importance of service discovery and learn how to implement it in C# and .NET using Eureka. We'll cover the fundamentals, practical implementation, and best practices to effectively manage service discovery in your microservices ecosystem.
Understanding Service Discovery
What is Service Discovery?
Service discovery is a design pattern that addresses the dynamic registration and discovery of services within a microservices architecture. It allows services to find each other and communicate without hardcoding their network locations or IP addresses. Instead, services register themselves with a service registry, and other services can query the registry to discover available services.
Why is it important in microservices architecture?
In a microservices environment, services are typically deployed dynamically, and their instances can come and go due to scaling, updates, or failures. This dynamic nature makes it challenging to maintain up-to-date information about service locations manually. Service discovery simplifies this task and offers several benefits:
Service Registration
How microservices register themselves
In a service discovery setup, each microservice registers itself with a service registry when it starts up. The registration typically includes information like the service name, version, network location, and health status. Service registries are responsible for maintaining a real-time database of available services.
Service Registration in C# with Eureka
One popular service registry tool is Netflix Eureka. Steeltoe is provided a very rich .Net library based on both Eureka and Consul for service discovery. In this article I used asp.net 6 and Steeltoe library of Eureka.
Running Eureka Server in Docker
Eureka Discovery service has two parts:
One of the best ways to install Eureka Server easily is running it in docker. You can simply install and run it using following command:
docker run -p 8761:8761 steeltoeoss/eureka-server
Note that 8761 is the default port of Eureka server. After running the docker, you are able to navigate to Eureka Server page by browsing to http//localhost:8761
Registering with Eureka
To be able to use Eureka client you need to install several packages using NuGet:
Steeltoe.Common.Hosting
Steeltoe.Discovery.ClientCore
We need to register the client service and add the middleware before use using these lines:
builder.Services.AddDiscoveryClient(builder.Configuration);
…
app.UseDiscoveryClient();
We also need to provide some configuration in appSettings.json:
// Eureka info
"eureka": {
"client": {
"serviceUrl": "https://localhost:8761/eureka/",
"shouldFetchRegistry": "false",
"shouldRegisterWithEureka": true,
???? "validateCertificates": false
},
??"instance": {
??????"appName": "myapi",
??????"port": "8080",
??????"ipAddress": "localhost",
??????"preferIpAddress": true
????}
}
With these settings we set the Url of the service a name (myapi) for this Api so later by providing this name to the server we will access this API base address
Now suppose from another service we call it “ClientService” we need to access “myapi”.
We need again to install same packages and add following settings in appSettings.json:
"eureka": {
"client": {
"serviceUrl": "https://locahost:8761/eureka/",
"shouldFetchRegistry": "true",
"shouldRegisterWithEureka": false,
"validateCertificates": false
}
}
With these settings, our client app knows about Eureka server.
领英推荐
builder.Services.AddDiscoveryClient(builder.Configuration);
builder.Services.AddHttpClient("myapi",
client => client.BaseAddress = new Url("https://myapiurl/"))
.AddServiceDiscovery();
The interesting thing here is that we associate the name “myapi” with an address which looks like a URL but really is the name of the service within Eureka that we want to access. Then, by using the AddServiceDiscovery this will be converted to an instance URL representing the instance of the service associated with the app name.
Service Discovery Clients
Service discovery clients are responsible for querying the service registry to find the location of other services. Once a service is registered, it can use a client library to discover and communicate with services it depends on.
Implementing Service Discovery Clients in C#
Let's say “ClientService” needs to use some APIs in myapi service. So In “ClientService” we need to inject IHttpClientFactory:
private readonly IHttpClientFactory _httpClientFactory;
public HomeController(IHttpClientFactory httpClientFactory, ILogger<HomeController> logger)
{
_httpClientFactory = httpClientFactory;
_logger = logger;
}?
And with now we can use the APIs from service:
public async Task<IActionResult> Index()
{
var client = _httpClientFactory.CreateClient("myapi");
var myview = await client.GetFromJsonAsync<IList<MyApiModel>>("apiname");
return View(myview);
}?
Docker and Kubernetes Integration
In containerized environments like Docker and Kubernetes, service discovery is often integrated into the platform. Kubernetes, for example, provides its own service discovery and load balancing mechanisms, making it easier to manage microservices.
Practical Implementation
Let's walk through a simplified real-world scenario where we implement service discovery in a C# .NET Core application. Imagine you have a microservices-based e-commerce system consisting of services like ProductService, OrderService, and UserService. These services need to find each other dynamically.
Step 1: Service Registration
Each service registers itself with the Eureka service registry when it starts up. You can use Eureka or other suitable libraries for this purpose. Ensure that you include essential information such as the service name, version, and network location in the registration.
Step 2: Service Discovery
When one service (e.g., OrderService) needs to communicate with another (e.g., ProductService), it uses a service discovery client (e.g., EurekaHttpClient) to discover available instances of the target service.
Step 3: Load Balancing
To achieve load balancing, you can integrate a load balancing library like Polly into your service. This library can be used to implement retry and failover strategies.
Best Practices and Considerations
Service discovery is a powerful pattern, but it's important to consider some best practices and potential challenges:
In conclusion, service discovery is a fundamental microservices design pattern that simplifies the dynamic registration and discovery of services within a distributed system. Implementing service discovery in C# and .NET can greatly improve the scalability, resilience, and maintainability of your microservices architecture. As you continue to explore microservices design patterns, consider how service discovery can benefit your specific use cases.
References:
?#microservices #servicediscovery #webapi #eureka #steeltoe
Consultor Informático
1 年Hay que aplicarlo en sistemas de misión crítica para disminuir los problemas.