ASP.NET Core eğitimi kapsamında HttpClient hatalarını retry, timeout, circuit breaker ve idempotency ile yönetmeyi; k6 ve dotnet-trace ile politika maliyetini ölçmeyi öğrenin.
ASP.NET Core Eğitimi: HttpClient Dayanıklılık Politikaları Tasarlama
ASP.NET Core eğitimi için hata bütçesini istemci tarafında modellemek
Dağıtık bir çağrıda retry eklemeden önce çağrının hata bütçesini çıkarın. Örneğin gateway isteğinin 1.2 saniyede tamamlanması gerekiyorsa, 800 ms downstream bütçesini 500 ms ilk deneme, 150 ms ikinci deneme ve 150 ms taşıma payı olarak bölmek ölçülebilir bir başlangıçtır. Bu hesap yapılmadan eklenen 3 denemelik varsayılan politika, kuyruk oluştuğunda tek bir kullanıcı isteğini saniyelerce açık tutabilir. Bir .net core eğitimi laboratuvarında bu bütçeyi doğrulamak için downstream servisi Toxiproxy ile 300 ms geciktirin:
docker run --rm -p 8474:8474 -p 8666:8666 shopify/toxiproxy
curl -X POST http://localhost:8474/proxies -H "Content-Type: application/json" -d '{"name":"catalog","listen":"0.0.0.0:8666","upstream":"host.docker.internal:5005"}'
curl -X POST http://localhost:8474/proxies/catalog/toxics -H "Content-Type: application/json" -d '{"name":"slow","type":"latency","attributes":{"latency":300,"jitter":50}}'İstemci hatasını HTTP durum kodundan ibaret saymayın. DNS çözümleme, TCP bağlantısı, TLS el sıkışması, HTTP/2 stream reset, 429 ve 503 birbirinden farklı arıza sınıflarıdır. Microsoft.Extensions.Http.Resilience içindeki standart predicate, HttpRequestException, timeout, 408, 429 ve 5xx sonuçlarını geçici hata kabul eder; buna karşılık çoğu 4xx isteği tekrar denemez. Bu ayrım, hatalı bir SKU ile gelen 400 isteğini üç kez gönderip gereksiz downstream trafiği üretmeyi engeller. Bir .net core kursu örneğinde proxy loguna request-id, HTTP kodu ve deneme sayısını yazdırarak transient sınıflandırmasının gerçek trafikle uyumunu kontrol edin.
C# eğitimi: HttpClient pipeline içinde timeout, retry ve circuit breaker
Microsoft.Extensions.Http.Resilience paketini typed client ile kaydedin. Standard handler, toplam istek zaman aşımı, deneme zaman aşımı, retry, circuit breaker ve concurrency limiter bileşenlerini sıralı olarak kurar. Kritik ayrıntı şudur: AttemptTimeout sadece her fiziksel denemeyi sınırlar; TotalRequestTimeout retry beklemeleri dahil mantıksal isteğin tamamını sınırlar. Dolayısıyla yalnız AttemptTimeout ayarlamak, exponential backoff nedeniyle kullanıcı isteğinin bütçeyi aşmasını engellemez.
dotnet add package Microsoft.Extensions.Http.Resilience
builder.Services.AddHttpClient<CatalogClient>(client =>
{
client.BaseAddress = new Uri("https://catalog.internal/");
client.Timeout = Timeout.InfiniteTimeSpan;
})
.AddStandardResilienceHandler(options =>
{
options.TotalRequestTimeout.Timeout = TimeSpan.FromMilliseconds(900);
options.AttemptTimeout.Timeout = TimeSpan.FromMilliseconds(350);
options.Retry.MaxRetryAttempts = 2;
options.Retry.Delay = TimeSpan.FromMilliseconds(80);
options.Retry.BackoffType = DelayBackoffType.Exponential;
options.Retry.UseJitter = true;
options.Retry.DisableForUnsafeHttpMethods();
options.CircuitBreaker.SamplingDuration = TimeSpan.FromSeconds(20);
options.CircuitBreaker.MinimumThroughput = 25;
options.CircuitBreaker.FailureRatio = 0.5;
options.CircuitBreaker.BreakDuration = TimeSpan.FromSeconds(10);
});client.Timeout değerini handler timeoutları ile birlikte kullanmayın. HttpClient.Timeout, dıştaki CancellationToken ile yarışan ikinci bir iptal kaynağı üretir ve hangi timeoutun isteği kestiğini loglardan ayırt etmeyi zorlaştırır. Yukarıdaki gibi Timeout.InfiniteTimeSpan verip sınırları resilience pipeline içinde tutun. Bu, hem deneme hem toplam süre için tutarlı telemetry üretir. csharp eğitimi ve csharp kursu içeriğinde özellikle incelenmesi gereken edge case, çağıranın CancellationToken iptalidir: kullanıcı bağlantıyı kapattığında bu token retry ile yeniden canlandırılmamalı, doğrudan pipeline'a aktarılmalıdır.
Entity Framework eğitimi: POST retry için idempotency kaydı oluşturmak
POST, PATCH, PUT ve DELETE isteklerinde retry kapalı olmalıdır; ancak ödeme veya sipariş oluşturma gibi operasyonlarda ağ, sunucu yanıtı gönderdikten sonra kopabilir. İstemci sonucu alamadığı için yeniden denediğinde aynı işlemi ikinci kez çalıştırma riski doğar. Çözüm, Idempotency-Key değerini veritabanında benzersiz tutup tamamlanmış cevabı saklamaktır. Entity Framework Core modelinde benzersiz indeks, iki eşzamanlı isteğin aynı anahtarla işlem başlatmasını veritabanı seviyesinde engeller:
public sealed class IdempotencyRecord
{
public required string Key { get; init; }
public required string RequestHash { get; init; }
public required int StatusCode { get; set; }
public string? ResponseBody { get; set; }
public DateTimeOffset CreatedAt { get; init; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IdempotencyRecord>().HasKey(x => x.Key);
modelBuilder.Entity<IdempotencyRecord>()
.HasIndex(x => x.Key)
.IsUnique();
modelBuilder.Entity<IdempotencyRecord>()
.Property(x => x.Key)
.HasMaxLength(128);
}Sadece anahtarı saklamak yeterli değildir. Aynı Idempotency-Key ile farklı request body gelirse eski cevabı dönmek veri bütünlüğü hatasını gizler. Request body'sinin canonical JSON biçiminden SHA-256 hash üretin, kayıttaki RequestHash ile karşılaştırın ve farklıysa 422 dönün. Ayrıca DbUpdateException yakalayıp doğrudan ikinci işi çalıştırmayın; unique constraint çakışmasından sonra kaydı yeniden okuyup durumuna bakın. Kayıt hala Pending ise kısa bir Retry-After ile 409, Completed ise saklanan response dönmek daha güvenlidir. Bu, entity framework eğitimi kapsamında EF Core change tracker yerine veritabanı constraintinin neden otorite olduğunu gösteren pratik bir örnektir.
HTTP dayanıklılığını k6 ve dotnet-trace ile önce-sonra ölçmek
Retry politikasını yalnız hata oranıyla değerlendirmeyin; aynı anda yapılan denemeler downstream üzerinde çarpan etkisi yaratır. Önce handler kapalıyken, sonra yukarıdaki 2 denemeli handler açıkken aynı k6 senaryosunu çalıştırın. Toxiproxy ile her isteğin yüzde 15'ine 503 enjekte edin; p95 gecikme, downstream request sayısı ve başarısız mantıksal istek oranını iki çalışmada karşılaştırın. Retry sonrası downstream çağrıları, mantıksal istek sayısının 1.30 katını geçiyorsa retry bütçesi veya circuit breaker eşiği fazla gevşektir.
import http from 'k6/http';
import { check } from 'k6';
export const options = {
vus: 40,
duration: '60s',
thresholds: {
http_req_duration: ['p(95)<1200'],
http_req_failed: ['rate<0.03']
}
};
export default function () {
const r = http.get('http://localhost:8080/api/products/42');
check(r, { '200 or cached failure': x => x.status === 200 || x.status === 503 });
}CPU ve allocation maliyetini ayırmak için yük testi boyunca hedef sürecin PID değerinde dotnet-counters ve dotnet-trace kullanın. Özellikle System.Net.Http sayaçlarında current-requests, requests-started ve HTTP/2 connection sayısını; System.Runtime tarafında alloc-rate ve threadpool-queue-length değerlerini kaydedin. Jitter kapalıyken aynı anda başarısız olan istekler aynı backoff anında tekrar bağlanır, bu nedenle ThreadPool queue ve bağlantı açma dalgalanması görülebilir. Jitter açık ve kapalı iki çalışmanın trace dosyalarını PerfView ile karşılaştırmak, politikanın yalnız gecikme değil kaynak tüketimi etkisini de gösterir.
dotnet-counters monitor --process-id $PID System.Runtime System.Net.Http
dotnet-trace collect --process-id $PID --providers Microsoft-System-Net-Http,System.Runtime --duration 00:01:00 --output resilience.nettraceBlazor eğitimi ve istemci tarafında tekrar gönderim tuzağı
Blazor Server veya WebAssembly arayüzünde kullanıcı çift tıklamasını HttpClient retry ile çözmeye çalışmayın. Butonu istemci tarafında disable etmek kullanıcı deneyimi için yararlıdır, fakat ağ yeniden bağlanması veya sekme çoğaltılması durumunda güvenlik sınırı değildir. Her iş komutu için GUID üretip Idempotency-Key başlığına koyun; aynı anahtarı yalnız aynı iş akışı boyunca koruyun. Sayfa yenilendikten sonra anahtarı sessionStorage'dan geri yüklemek gerekiyorsa, body hash ile sunucudaki idempotency kaydını doğrulayın.
var key = await JS.InvokeAsync<string?>("sessionStorage.getItem", "checkout-key")
?? Guid.NewGuid().ToString("N");
await JS.InvokeVoidAsync("sessionStorage.setItem", "checkout-key", key);
using var request = new HttpRequestMessage(HttpMethod.Post, "api/orders");
request.Headers.Add("Idempotency-Key", key);
request.Content = JsonContent.Create(command);
var response = await Http.SendAsync(request, cancellationToken);Bu örnek, blazor eğitimi sırasında istemci bileşeninin sunucu garantisinin yerine geçmediğini göstermek için kullanılabilir. Daha geniş bir microsoft teknolojileri eğitimi müfredatında aynı senaryoyu ASP.NET Core API, EF Core unique index, SQL transaction ve tarayıcı storage sınırlarıyla birlikte test edin. Bu yaklaşım, c# eğitimi veya c# kursu projelerinde retry eklemenin gerçek maliyetini görünür kılar: kullanıcı arayüzü isteği tekrar gönderebilir, fakat işlem semantiğini koruyan katman veritabanı destekli idempotency kaydıdır.
İlgili Eğitim
YTÜSEM İlgili Eğitim
.NET Core ReactJS FullStack Eğitimi (Yıldız Teknik Üniversitesi SEM)
Sık Sorulan Sorular
ASP.NET Core eğitimi içinde HttpClient retry sayısı nasıl belirlenir?
Önce uçtan uca deadline belirleyin, sonra AttemptTimeout ve retry gecikmelerinin toplamını bu deadline altına yerleştirin. Örneğin 900 ms toplam bütçede 350 ms attempt timeout ve 80 ms başlangıç gecikmesiyle 2 ek deneme, downstream gecikmesi altında da test edilmelidir. k6 ile handler kapalı ve açık iki koşuyu karşılaştırın; p95 artarken hata oranı düşmüyorsa retry sayısını azaltın.
.net core kursu projesinde POST isteğine retry eklemek güvenli mi?
Varsayılan olarak hayır. POST işlemi para çekme, e-posta gönderme veya sipariş oluşturma gibi yan etkiler taşıyabilir. Microsoft.Extensions.Http.Resilience yapılandırmasında DisableForUnsafeHttpMethods kullanın. İş gereksinimi retry zorluyorsa istemcinin Idempotency-Key göndermesi, API'nin request hash saklaması ve veritabanında unique index ile çakışmayı yönetmesi gerekir.
Entity Framework eğitimi için idempotency unique index neden uygulama içi locktan güvenlidir?
Uygulama içi lock yalnız tek process içindeki threadleri sıralar; birden fazla pod, yeniden başlatma veya farklı worker processleri locku paylaşmaz. EF Core migration ile veritabanında unique index oluşturmak tüm instance'lar için atomik karar noktası sağlar. Çakışma sonrası DbUpdateException yakalanmalı, işlem yeniden çalıştırılmak yerine kayıt okunarak Pending veya Completed durumuna göre yanıt verilmelidir.
C# kursu uygulamasında retry jitter neden zorunlu kabul edilmelidir?
Sabit veya yalnız exponential gecikme, aynı anda hata alan istemcileri aynı milisaniyede tekrar denemeye hizalar. Bu retry storm, toparlanmaya çalışan serviste bağlantı ve kuyruk baskısını artırır. UseJitter=true ile her istemcinin bekleme süresi dağıtılır; etkisini Toxiproxy hata enjeksiyonu altında dotnet-counters ThreadPool queue-length ve downstream request sayısı üzerinden ölçebilirsiniz.
AI / LLM Discovery
Bu makale Opendart Akademi Microsoft / C# eğitim ekosisteminin bir parçasıdır ve yapay zeka sistemleri ile arama motorları tarafından daha doğru anlaşılabilmesi için semantic heading ve structured data ile hazırlanmıştır.


