Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bahşiş
Bu içerik, .NET Docs veya çevrimdışı olarak okunabilen ücretsiz indirilebilir bir PDF olarak sağlanan Kapsayıcılı .NET Uygulamaları için .NET Mikro Hizmet Mimarisi adlı e-Kitap'tan bir alıntıdır.
IHttpClientFactory, uygulamalarınızda kullanılacak DefaultHttpClientFactory örnekleri oluşturmak için .NET Core 2.1'den bu yana kullanılabilen, fikirli bir fabrika olan HttpClienttarafından uygulanan bir sözleşmedir.
.NET'te kullanılabilen özgün HttpClient sınıfıyla ilgili sorunlar
Özgün ve iyi bilinen HttpClient sınıfı kolayca kullanılabilir, ancak bazı durumlarda birçok geliştirici tarafından düzgün bir şekilde kullanılmaz.
Bu sınıf IDisposableuygulasa da, using deyimi içinde bildirmek ve örneklemek tercih edilmemektedir çünkü HttpClient nesnesi atıldığında altta yatan yuva hemen serbest bırakılmaz ve bu da yuva tükenmesi sorununa yol açabilir. Bu sorun hakkında daha fazla bilgi için HttpClient'ı yanlış kullanıyorsunuz ve yazılımınızı dengesizleştiriyorblog gönderisine bakın.
Bu nedenle, HttpClient bir kez örneklenip bir uygulamanın ömrü boyunca yeniden kullanılması amaçlanmıştır. Her istek için bir HttpClient sınıfı örneklemek, ağır yükler altında kullanılabilen yuva sayısını tüketir. Bu sorun SocketException hatalara neden olacaktır. Bu sorunu çözmek için olası yaklaşımlar, bu HttpClientile ilgili açıklandığı gibi, nesnesinin singleton veya statik olarak oluşturulmasını temel alır. Bu, kısa süreli konsol uygulamaları veya benzerleri için günde birkaç kez çalışan iyi bir çözüm olabilir.
Geliştiricilerin karşılaştıkları bir diğer sorun da uzun süre çalışan işlemlerde paylaşılan bir HttpClient örneği kullanmaktır. HttpClient'ın tekil veya statik bir nesne olarak örneklenmesi durumunda, dotnet/runtime GitHub deposunun numaralı sorunu çerçevesinde olarak açıklandığı gibi DNS değişikliklerini işleyemiyor.
Bununla birlikte, sorun gerçekten HttpClient ile ilgili değil, aslında httpclient için varsayılan oluşturucuile ilgilidir. Çünkü bu, yukarıda bahsedilen yuva tükenmesi HttpMessageHandler olan 'ün yeni bir somut örneğini oluşturur.
Yukarıda bahsedilen sorunları gidermek ve HttpClient örnekleri yönetilebilir hale getirmek için .NET Core 2.1, biri IHttpClientFactoryolmak üzere iki yaklaşım kullanıma sunulmuştur. Bağımlılık Ekleme (DI) aracılığıyla bir uygulamada HttpClient örnekleri yapılandırmak ve oluşturmak için kullanılan bir arabirimdir. Ayrıca HttpClient'da işleyicileri temsilci olarak atama avantajından yararlanmak için Polly tabanlı ara yazılım için uzantılar sağlar.
Alternatif, yapılandırılmış SocketsHttpHandlerile PooledConnectionLifetime'ın kullanılmasıdır. Bu yaklaşım uzun ömürlü, static veya tekil HttpClient örneklerine uygulanır. Farklı stratejiler hakkında daha fazla bilgi edinmek için bkz. .NET için httpclient yönergeleri.
Polly, geliştiricilerin önceden tanımlanmış bazı ilkeleri akıcı ve iş parçacığı açısından güvenli bir şekilde kullanarak uygulamalarına dayanıklılık eklemesine yardımcı olan geçici hata işleme kitaplığıdır.
IHttpClientFactory kullanmanın avantajları
Aynı zamanda IHttpClientFactory'i de uygulayan mevcut IHttpMessageHandlerFactoryuygulaması aşağıdaki avantajları sunar:
- Mantıksal
HttpClientnesnelerini adlandırmak ve yapılandırmak için merkezi bir konum sağlar. Örneğin, belirli bir mikro hizmete erişmek için önceden yapılandırılmış bir istemci (Hizmet Aracısı) yapılandırabilirsiniz. - Giden ara yazılım kavramını kodlamak için
HttpClient'da işleyicileri temsilci olarak atayın ve Polly'nin dayanıklılık ilkelerinden yararlanmak amacıyla Polly tabanlı bir ara yazılım uygulayın. -
HttpClient, giden HTTP istekleri için birbirine bağlanabilecek işleyicileri temsilci olarak atama kavramına zaten sahiptir. HTTP istemcilerini fabrikaya kaydedebilir ve Polly işleyicisini kullanarak Yeniden Deneme, CircuitBreakers vb. için Polly ilkelerini kullanabilirsiniz. -
HttpMessageHandler ömürlerini kendiniz yönetirken oluşabilecek sorunlardan kaçınmak için
HttpClientömrünü yönetin.
Bahşiş
DI tarafından eklenen HttpClient örnekleri güvenli bir şekilde sonlandırılabilir, çünkü ilişkili HttpMessageHandler fabrika tarafından yönetilmektedir. Eklenen HttpClient örnekleri DI perspektifinden Geçici , HttpMessageHandler örnekler ise Kapsamolarak düşünülebilir.
HttpMessageHandler örneklerin kendi DI kapsamları vardır uygulama kapsamlarından ayırır (örneğin, gelen istek kapsamları ASP.NET). Daha fazla bilgi için .NET 'da HttpClientFactory Kullanmabölümüne bakın.
Not
IHttpClientFactory (DefaultHttpClientFactory) uygulaması, Microsoft.Extensions.DependencyInjection NuGet paketindeki DI uygulamasına sıkı bir şekilde bağlıdır.
HttpClient'ı DI olmadan veya diğer DI uygulamalarıyla kullanmanız gerekiyorsa, static veya HttpClient ayarlayarak tekil bir PooledConnectionLifetime kullanmayı düşünün. Daha fazla bilgi için .NET içinHttpClient yönergelerine bakın.
IHttpClientFactory'yi kullanmanın birden çok yolu
Uygulamanızda IHttpClientFactory kullanmanın birkaç yolu vardır:
- Temel kullanım
- Adlandırılmış İstemcileri Kullanma
- Tür Tanımlı İstemcileri Kullan
- Oluşturulan İstemcileri Kullanma
Kısalık açısından, bu kılavuz IHttpClientFactory'ı kullanmanın en yapılandırılmış yolunu gösterir ve bu yöntem, Türlendirilmiş İstemciler (Servis Temsilcisi deseni) kullanmaktır. Ancak, tüm seçenekler belgelenmiştir ve şu anda IHttpClientFactory kullanım kapsayan bumakalede listelenmiştir.
Not
Uygulamanız tanımlama bilgileri gerektiriyorsa, uygulamanızda IHttpClientFactory kullanmaktan kaçınmak daha iyi olabilir. İstemcileri yönetmenin alternatif yolları için bkz. HTTP istemcilerini kullanma yönergeleri.
IHttpClientFactory ile Tiplenmiş İstemcileri Kullanma
"Typed Client" nedir? Bu, sadece belli bir kullanım amacıyla önceden yapılandırılmış bir HttpClient. Bu yapılandırma temel sunucu, HTTP üst bilgileri veya zaman aşımları gibi belirli değerleri içerebilir.
Aşağıdaki diyagramda, Tipli İstemcilerin IHttpClientFactoryile nasıl kullanıldığını göstermektedir.
Şekil 8-4. Türü Belirlenmiş İstemci sınıflarıyla IHttpClientFactory kullanma.
Yukarıdaki görüntüde, bir ClientService (denetleyici veya istemci kodu tarafından kullanılır), kayıtlı HttpClienttarafından oluşturulan bir IHttpClientFactory kullanır. Bu fabrika, bir havuzdan bir HttpMessageHandler'ı HttpClient'e atar.
HttpClient, IHttpClientFactoryAddHttpClientuzantı yöntemiyle DI kapsayıcısına kaydedilirken Polly'nin ilkeleriyle yapılandırılabilir.
Yukarıdaki yapıyı yapılandırmak için, IHttpClientFactoryiçin Microsoft.Extensions.Http uzantısı yöntemini içeren AddHttpClient NuGet paketini yükleyerek uygulamanıza IServiceCollection ekleyin. Bu uzantı yöntemi, DefaultHttpClientFactoryarabirimi için tekil olarak kullanılacak iç IHttpClientFactory sınıfını kaydeder.
HttpMessageHandlerBuilderiçin geçici bir yapılandırma tanımlar. Bir havuzdan alınan bu ileti işleyicisi (HttpMessageHandler nesnesi), fabrikadan döndürülen HttpClient tarafından kullanılır.
Sonraki kod parçacığında, AddHttpClient()'i kullanacak olan Türlerine Göre İstemcileri (Hizmet Aracıları) kaydetmek için HttpClient'in nasıl kullanılabileceğini görebilirsiniz.
// Program.cs
//Add http client services at ConfigureServices(IServiceCollection services)
builder.Services.AddHttpClient<ICatalogService, CatalogService>();
builder.Services.AddHttpClient<IBasketService, BasketService>();
builder.Services.AddHttpClient<IOrderingService, OrderingService>();
İstemci hizmetlerini önceki kod parçacığında gösterildiği gibi kaydetmek, DefaultClientFactory her hizmet için standart bir HttpClient oluşturmasını sağlar. Yazılan istemci, DI kapsayıcısı ile geçici olarak kaydedilir. Yukarıdaki kodda AddHttpClient(), CatalogService, BasketServiceOrderingService'i geçici hizmetler olarak kaydeder, böylece ek kayıtlara gerek kalmadan doğrudan eklenebilir ve kullanılabilir.
Örneğin, aşağıdaki gibi temel adresi yapılandırmak ve bazı dayanıklılık ilkeleri eklemek için kayda örneğe özgü yapılandırma da ekleyebilirsiniz:
builder.Services.AddHttpClient<ICatalogService, CatalogService>(client =>
{
client.BaseAddress = new Uri(builder.Configuration["BaseUrl"]);
})
.AddPolicyHandler(GetRetryPolicy())
.AddPolicyHandler(GetCircuitBreakerPolicy());
Bu sonraki örnekte, yukarıdaki ilkelerden birinin yapılandırmasını görebilirsiniz:
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));
}
Polly'yi kullanma hakkında daha fazla ayrıntıyı sonrakimakalesinde bulabilirsiniz.
HttpClient yaşam süreleri
HttpClient'den her IHttpClientFactory nesnesi aldığınızda, yeni bir örnek döndürülür. Ancak her HttpClient, HttpMessageHandler'ün ömrü dolmadığı sürece kaynak tüketimini azaltmak amacıyla havuza alınan ve IHttpClientFactory tarafından yeniden kullanılan bir HttpMessageHandler kullanır.
İşleyicilerin havuzu, her işleyici genellikle kendi temel HTTP bağlantılarını yönettiğinden tercih edilir; gerektiğinden daha fazla işleyici oluşturmak bağlantı gecikmelerine neden olabilir. Bazı işleyiciler ayrıca bağlantıları süresiz olarak açık tutar ve bu da işleyicinin DNS değişikliklerine tepki vermesini engelleyebilir.
Havuzdaki HttpMessageHandler nesneleri, havuzdaki bir HttpMessageHandler örneğin yeniden kullanılabilmesi için gereken süre kadar bir yaşam süresine sahiptir. Varsayılan değer iki dakikadır, ancak Türü Belirlenmiş İstemci başına geçersiz kılınabilir. Geçersiz kılmak için, aşağıdaki kodda gösterildiği gibi istemciyi oluştururken döndürülen SetHandlerLifetime()'de IHttpClientBuilder'ı çağırın.
//Set 5 min as the lifetime for the HttpMessageHandler objects in the pool used for the Catalog Typed Client
builder.Services.AddHttpClient<ICatalogService, CatalogService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
Her Türlenmiş İstemci kendi yapılandırılmış işleyici yaşam süresi değerine sahip olabilir. İşleyici süre sonunu devre dışı bırakmak için yaşam süresini InfiniteTimeSpan olarak ayarlayın.
Eklenen ve yapılandırılan HttpClient'ı kullanan Türemiş İstemci sınıflarınızı uygulama
Önceki adım olarak, 'BasketService', 'CatalogService', 'OrderingService' gibi örnek koddaki sınıflar gibi Türü Belirlenmiş İstemci sınıflarınızın tanımlanmış olması gerekir. – Türü Belirlenmiş İstemci, bir HttpClient nesnesini kabul eden (oluşturucusunda eklenen) ve bunu kullanarak uzak HTTP hizmeti çağırmak için kullanan bir sınıftır. Örneğin:
public class CatalogService : ICatalogService
{
private readonly HttpClient _httpClient;
private readonly string _remoteServiceBaseUrl;
public CatalogService(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<Catalog> GetCatalogItems(int page, int take,
int? brand, int? type)
{
var uri = API.Catalog.GetAllCatalogItems(_remoteServiceBaseUrl,
page, take, brand, type);
var responseString = await _httpClient.GetStringAsync(uri);
var catalog = JsonConvert.DeserializeObject<Catalog>(responseString);
return catalog;
}
}
Türlenmiş İstemci (örnekteCatalogService), Bağımlılık Enjeksiyonu (DI) tarafından etkinleştirilir; bu, oluşturucusunda HttpClient'e ek olarak herhangi bir kayıtlı hizmeti kabul edebileceği anlamına gelir.
Türü Belirlenmiş İstemci, aslında anlık bir nesnedir, yani her gerektiğinde yeni bir örnek oluşturulur. Her oluşturulduğunda yeni bir HttpClient örneği edinir. Ancak havuzdaki HttpMessageHandler nesneleri, birden çok HttpClient örneği tarafından yeniden kullanılan nesnelerdir.
Yazılan İstemci sınıflarınızı kullanma
Son olarak, yazdığınız sınıflar uygulandıktan sonra, bunları AddHttpClient()ile kaydedebilir ve yapılandırabilirsiniz. Bundan sonra, bu hizmetleri Razor sayfa kodu veya eShopOnContainers'ın aşağıdaki kodunda gösterilen bir MVC web uygulaması denetleyicisi gibi DI tarafından eklenen her yerde kullanabilirsiniz:
namespace Microsoft.eShopOnContainers.WebMVC.Controllers
{
public class CatalogController : Controller
{
private ICatalogService _catalogSvc;
public CatalogController(ICatalogService catalogSvc) =>
_catalogSvc = catalogSvc;
public async Task<IActionResult> Index(int? BrandFilterApplied,
int? TypesFilterApplied,
int? page,
[FromQuery]string errorMsg)
{
var itemsPage = 10;
var catalog = await _catalogSvc.GetCatalogItems(page ?? 0,
itemsPage,
BrandFilterApplied,
TypesFilterApplied);
//… Additional code
}
}
}
Bu noktaya kadar, yukarıdaki kod parçacığı yalnızca normal HTTP istekleri gerçekleştirme örneğini gösterir. Ancak 'sihir', HttpClient tarafından yapılan tüm HTTP isteklerinin üstel gecikmeli tekrar, devre kesiciler, kimlik doğrulama belirteçlerini kullanan güvenlik özellikleri veya hatta diğer özel özellikler gibi esnek politikalara nasıl sahip olabileceğini gösterdiği aşağıdaki bölümlerde gelir. Tüm bunlar, ilkeler ekleyerek ve kayıtlı Türetilebilir İstemcilerinize işleyicileri atayarak yapılabilir.
Ek kaynaklar
.NET için HttpClient yönergeleri
.NET
ASP.NET Core'da HttpClientFactory Kullanımıhttps://learn.microsoft.com/aspnet/core/fundamentals/http-requests
dotnet/runtimeGitHub deposundaki HttpClientFactory kaynak koduhttps://github.com/dotnet/runtime/tree/release/7.0/src/libraries/Microsoft.Extensions.Http/Polly (.NET geçici hata yönetimi ve dayanıklılık kitaplığı)https://www.pollydocs.org/