Microsoft.Extensions.ServiceDiscovery
9.0.0
Prefix Reserved
dotnet add package Microsoft.Extensions.ServiceDiscovery --version 9.0.0
NuGet\Install-Package Microsoft.Extensions.ServiceDiscovery -Version 9.0.0
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="9.0.0" />
paket add Microsoft.Extensions.ServiceDiscovery --version 9.0.0
#r "nuget: Microsoft.Extensions.ServiceDiscovery, 9.0.0"
// Install Microsoft.Extensions.ServiceDiscovery as a Cake Addin #addin nuget:?package=Microsoft.Extensions.ServiceDiscovery&version=9.0.0 // Install Microsoft.Extensions.ServiceDiscovery as a Cake Tool #tool nuget:?package=Microsoft.Extensions.ServiceDiscovery&version=9.0.0
Microsoft.Extensions.ServiceDiscovery
The Microsoft.Extensions.ServiceDiscovery
library is designed to simplify the integration of service discovery patterns in .NET applications. Service discovery is a key component of most distributed systems and microservices architectures. This library provides a straightforward way to resolve service names to endpoint addresses.
In typical systems, service configuration changes over time. Service discovery accounts for by monitoring endpoint configuration using push-based notifications where supported, falling back to polling in other cases. When endpoints are refreshed, callers are notified so that they can observe the refreshed results.
How it works
Service discovery uses configured providers to resolve service endpoints. When service endpoints are resolved, each registered provider is called in the order of registration to contribute to a collection of service endpoints (an instance of ServiceEndpointSource
).
Providers implement the IServiceEndpointProvider
interface. They are created by an instance of IServiceEndpointProviderProvider
, which are registered with the .NET dependency injection system.
Developers typically add service discovery to their HttpClient
using the IHttpClientFactory
with the AddServiceDiscovery
extension method.
Services can be resolved directly by calling ServiceEndpointResolver
's GetEndpointsAsync
method, which returns a collection of resolved endpoints.
Change notifications
Service configuration can change over time. Service discovery accounts for by monitoring endpoint configuration using push-based notifications where supported, falling back to polling in other cases. When endpoints are refreshed, callers are notified so that they can observe the refreshed results. To subscribe to notifications, callers use the ChangeToken
property of ServiceEndpointCollection
. For more information on change tokens, see Detect changes with change tokens in ASP.NET Core.
Extensibility using features
Service endpoints (ServiceEndpoint
instances) and collections of service endpoints (ServiceEndpointCollection
instances) expose an extensible IFeatureCollection
via their Features
property. Features are exposed as interfaces accessible on the feature collection. These interfaces can be added, modified, wrapped, replaced or even removed at resolution time by providers. Features which may be available on a ServiceEndpoint
include:
IHostNameFeature
: exposes the host name of the resolved endpoint, intended for use with Server Name Identification (SNI) and Transport Layer Security (TLS).
Resolution order
The providers included in the Microsoft.Extensions.ServiceDiscovery
series of packages skip resolution if there are existing endpoints in the collection when they are called. For example, consider a case where the following providers are registered: Configuration, DNS SRV, Pass-through. When resolution occurs, the providers will be called in-order. If the Configuration providers discovers no endpoints, the DNS SRV provider will perform resolution and may add one or more endpoints. If the DNS SRV provider adds an endpoint to the collection, the Pass-through provider will skip its resolution and will return immediately instead.
Getting Started
Installation
To install the library, use the following NuGet command:
dotnet add package Microsoft.Extensions.ServiceDiscovery
Usage example
In the Program.cs file of your project, call the AddServiceDiscovery
extension method to add service discovery to the host, configuring default service endpoint providers.
builder.Services.AddServiceDiscovery();
Add service discovery to an individual IHttpClientBuilder
by calling the AddServiceDiscovery
extension method:
builder.Services.AddHttpClient<CatalogServiceClient>(c =>
{
c.BaseAddress = new("https://catalog"));
}).AddServiceDiscovery();
Alternatively, you can add service discovery to all HttpClient
instances by default:
builder.Services.ConfigureHttpClientDefaults(http =>
{
// Turn on service discovery by default
http.AddServiceDiscovery();
});
Resolving service endpoints from configuration
The AddServiceDiscovery
extension method adds a configuration-based endpoint provider by default.
This provider reads endpoints from the .NET Configuration system.
The library supports configuration through appsettings.json
, environment variables, or any other IConfiguration
source.
Here is an example demonstrating how to configure endpoints for the service named catalog via appsettings.json
:
{
"Services": {
"catalog": {
"https": [
"https://localhost:8443",
"https://10.46.24.90:443"
]
}
}
}
The above example adds two endpoints for the service named catalog: https://localhost:8443
, and "https://10.46.24.90:443"
.
Each time the catalog is resolved, one of these endpoints will be selected.
If service discovery was added to the host using the AddServiceDiscoveryCore
extension method on IServiceCollection
, the configuration-based endpoint provider can be added by calling the AddConfigurationServiceEndpointProvider
extension method on IServiceCollection
.
Configuration
The configuration provider is configured using the ConfigurationServiceEndpointProviderOptions
class, which offers these configuration options:
SectionName
: The name of the configuration section that contains service endpoints. It defaults to"Services"
.ShouldApplyHostNameMetadata
: A delegate used to determine if host name metadata should be applied to resolved endpoints. It defaults to a function that returnsfalse
.
To configure these options, you can use the Configure
extension method on the IServiceCollection
within your application's startup class or main program file:
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ConfigurationServiceEndpointProviderOptions>(options =>
{
options.SectionName = "MyServiceEndpoints";
// Configure the logic for applying host name metadata
options.ShouldApplyHostNameMetadata = endpoint =>
{
// Your custom logic here. For example:
return endpoint.Endpoint is DnsEndPoint dnsEp && dnsEp.Host.StartsWith("internal");
};
});
This example demonstrates setting a custom section name for your service endpoints and providing a custom logic for applying host name metadata based on a condition.
Scheme selection when resolving HTTP(S) endpoints
It is common to use HTTP while developing and testing a service locally and HTTPS when the service is deployed. Service Discovery supports this by allowing for a priority list of URI schemes to be specified in the input string given to Service Discovery. Service Discovery will attempt to resolve the services for the schemes in order and will stop after an endpoint is found. URI schemes are separated by a +
character, for example: "https+http://basket"
. Service Discovery will first try to find HTTPS endpoints for the "basket"
service and will then fall back to HTTP endpoints. If any HTTPS endpoint is found, Service Discovery will not include HTTP endpoints.
Schemes can be filtered by configuring the AllowedSchemes
and AllowAllSchemes
properties on ServiceDiscoveryOptions
. The AllowAllSchemes
property is used to indicate that all schemes are allowed. By default, AllowAllSchemes
is true
and all schemes are allowed. Schemes can be restricted by setting AllowAllSchemes
to false
and adding allowed schemes to the AllowedSchemes
property. For example, to allow only HTTPS:
services.Configure<ServiceDiscoveryOptions>(options =>
{
options.AllowAllSchemes = false;
options.AllowedSchemes = ["https"];
});
To explicitly allow all schemes, set the ServiceDiscoveryOptions.AllowAllSchemes
property to true
:
services.Configure<ServiceDiscoveryOptions>(options => options.AllowAllSchemes = true);
Resolving service endpoints using platform-provided service discovery
Some platforms, such as Azure Container Apps and Kubernetes (if configured), provide functionality for service discovery without the need for a service discovery client library. When an application is deployed to one of these environments, it may be preferable to use the platform's existing functionality instead. The pass-through provider exists to support this scenario while still allowing other provider (such as configuration) to be used in other environments, such as on the developer's machine, without requiring a code change or conditional guards.
The pass-through provider performs no external resolution and instead resolves endpoints by returning the input service name represented as a DnsEndPoint
.
The pass-through provider is configured by-default when adding service discovery via the AddServiceDiscovery
extension method.
If service discovery was added to the host using the AddServiceDiscoveryCore
extension method on IServiceCollection
, the pass-through provider can be added by calling the AddPassThroughServiceEndpointProvider
extension method on IServiceCollection
.
In the case of Azure Container Apps, the service name should match the app name. For example, if you have a service named "basket", then you should have a corresponding Azure Container App named "basket".
Service discovery in .NET Aspire
.NET Aspire includes functionality for configuring the service discovery at development and testing time. This functionality works by providing configuration in the format expected by the configuration-based endpoint provider described above from the .NET Aspire AppHost project to the individual service projects added to the application model.
Configuration for service discovery is only added for services which are referenced by a given project. For example, consider the following AppHost program:
var builder = DistributedApplication.CreateBuilder(args);
var catalog = builder.AddProject<Projects.CatalogService>("catalog");
var basket = builder.AddProject<Projects.BasketService>("basket");
var frontend = builder.AddProject<Projects.MyFrontend>("frontend")
.WithReference(basket)
.WithReference(catalog);
In the above example, the frontend project references the catalog project and the basket project. The two WithReference
calls instruct the .NET Aspire application to pass service discovery information for the referenced projects (catalog, and basket) into the frontend project.
Named endpoints
Some services expose multiple, named endpoints. Named endpoints can be resolved by specifying the endpoint name in the host portion of the HTTP request URI, following the format scheme://_endpointName.serviceName
. For example, if a service named "basket" exposes an endpoint named "dashboard", then the URI https+http://_dashboard.basket
can be used to specify this endpoint, for example:
builder.Services.AddHttpClient<BasketServiceClient>(
static client => client.BaseAddress = new("https+http://basket"));
builder.Services.AddHttpClient<BasketServiceDashboardClient>(
static client => client.BaseAddress = new("https+http://_dashboard.basket"));
In the above example, two HttpClient
s are added: one for the core basket service and one for the basket service's dashboard.
Named endpoints using configuration
With the configuration-based endpoint provider, named endpoints can be specified in configuration by prefixing the endpoint value with _endpointName.
, where endpointName
is the endpoint name. For example, consider this appsettings.json configuration which defined a default endpoint (with no name) and an endpoint named "dashboard":
{
"Services": {
"basket":
"https": "https://10.2.3.4:8080", /* the https endpoint, requested via https://basket */
"dashboard": "https://10.2.3.4:9999" /* the "dashboard" endpoint, requested via https://_dashboard.basket */
}
}
}
Named endpoints in .NET Aspire
.NET Aspire uses the configuration-based provider at development and testing time, providing convenient APIs for configuring named endpoints which are then translated into configuration for the target services. For example:
var builder = DistributedApplication.CreateBuilder(args);
var basket = builder.AddProject<Projects.BasketService>("basket")
.WithEndpoint(hostPort: 9999, scheme: "https", name: "admin");
var adminDashboard = builder.AddProject<Projects.MyDashboardAggregator>("admin-dashboard")
.WithReference(basket.GetEndpoint("admin"));
var frontend = builder.AddProject<Projects.Frontend>("frontend")
.WithReference(basket);
In the above example, the "basket" service exposes an "admin" endpoint in addition to the default "http" endpoint which it exposes. This endpoint is consumed by the "admin-dashboard" project, while the "frontend" project consumes all endpoints from "basket". Alternatively, the "frontend" project could be made to consume only the default "http" endpoint from "basket" by using the GetEndpoint(string name)
method, as in the following example:
// The preceding code is the same as in the above sample
var frontend = builder.AddProject<Projects.Frontend>("frontend")
.WithReference(basket.GetEndpoint("https"));
Named endpoints in Kubernetes using DNS SRV
When deploying to Kubernetes, the DNS SRV service endpoint provider can be used to resolve named endpoints. For example, the following resource definition will result in a DNS SRV record being created for an endpoint named "default" and an endpoint named "dashboard", both on the service named "basket".
apiVersion: v1
kind: Service
metadata:
name: basket
spec:
selector:
name: basket-service
clusterIP: None
ports:
- name: default
port: 8080
- name: dashboard
port: 8888
To configure a service to resolve the "dashboard" endpoint on the "basket" service, add the DNS SRV service endpoint provider to the host builder as follows:
builder.Services.AddServiceDiscoveryCore();
builder.Services.AddDnsSrvServiceEndpointProvider();
The special port name "default" is used to specify the default endpoint, resolved using the URI https://basket
.
As in the previous example, add service discovery to an HttpClient
for the basket service:
builder.Services.AddHttpClient<BasketServiceClient>(
static client => client.BaseAddress = new("https://basket"));
Similarly, the "dashboard" endpoint can be targeted as follows:
builder.Services.AddHttpClient<BasketServiceDashboardClient>(
static client => client.BaseAddress = new("https://_dashboard.basket"));
Named endpoints in Azure Container Apps
Named endpoints are not currently supported for services deployed to Azure Container Apps.
Feedback & contributing
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net8.0
- Microsoft.Extensions.Configuration.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 8.0.2)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Features (>= 8.0.11)
- Microsoft.Extensions.Http (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
- Microsoft.Extensions.Primitives (>= 8.0.0)
- Microsoft.Extensions.ServiceDiscovery.Abstractions (>= 9.0.0)
NuGet packages (22)
Showing the top 5 NuGet packages that depend on Microsoft.Extensions.ServiceDiscovery:
Package | Downloads |
---|---|
Microsoft.Extensions.ServiceDiscovery.Yarp
Provides extensions for service discovery for the YARP reverse proxy. |
|
RESTworld.AspNetCore
Package Description |
|
Eaf.AspNetCore
Enterprise Application Foundation - AspNetCore integration |
|
Microsoft.Extensions.ServiceDiscovery.Dns
Provides extensions to HttpClient to resolve well-known hostnames to concrete endpoints based on DNS records. Useful for service resolution in orchestrators such as Kubernetes. |
|
Rocket.Surgery.LaunchPad.Foundation
Package Description |
GitHub repositories (30)
Showing the top 5 popular GitHub repositories that depend on Microsoft.Extensions.ServiceDiscovery:
Repository | Stars |
---|---|
dotnet/eShop
A reference .NET application implementing an eCommerce site
|
|
fullstackhero/dotnet-starter-kit
Production Grade Cloud-Ready .NET 8 Starter Kit (Web API + Blazor Client) with Multitenancy Support, and Clean/Modular Architecture that saves roughly 200+ Development Hours! All Batteries Included.
|
|
dotnet/aspire
Tools, templates, and packages to accelerate building observable, production-ready apps
|
|
oskardudycz/EventSourcing.NetCore
Examples and Tutorials of Event Sourcing in .NET
|
|
davidfowl/TodoApp
Todo application with ASP.NET Core Blazor WASM, Minimal APIs and Authentication
|
Version | Downloads | Last updated |
---|---|---|
9.0.0 | 43,870 | 11/12/2024 |
9.0.0-rc.1.24511.1 | 12,981 | 10/15/2024 |
8.2.2 | 98,274 | 10/24/2024 |
8.2.1 | 156,184 | 9/26/2024 |
8.2.0 | 247,225 | 8/29/2024 |
8.1.0 | 308,388 | 7/23/2024 |
8.0.2 | 160,749 | 6/28/2024 |
8.0.1 | 275,710 | 5/21/2024 |
8.0.0 | 174,605 | 5/21/2024 |
8.0.0-preview.7.24251.11 | 62,358 | 5/7/2024 |
8.0.0-preview.6.24214.1 | 60,143 | 4/23/2024 |
8.0.0-preview.5.24201.12 | 49,505 | 4/9/2024 |
8.0.0-preview.4.24156.9 | 86,039 | 3/12/2024 |
8.0.0-preview.3.24105.21 | 90,701 | 2/13/2024 |
8.0.0-preview.2.23619.3 | 83,797 | 12/20/2023 |
8.0.0-preview.1.23557.2 | 73,788 | 11/14/2023 |