Bu ASP.NET Core eğitimi, istemci kopmalarını ve süre aşımını CancellationToken ile uçtan uca taşıyarak EF Core, HttpClient ve CPU ağırlıklı işlemlerde boşa çalışan kaynakları nasıl sınırlayacağınızı gösterir.
ASP.NET Core Eğitimi: İptal Belirteçleriyle Yük Altında Doğru Akış
ASP.NET Core Eğitimi: İstek ömrünü tek bir iptal bütçesine bağlamak
Bir .net core eğitimi veya .net core kursu kapsamında CancellationToken genellikle sadece endpoint parametresi olarak anlatılır. Üretimde kritik nokta, token'ın istemci kopması, uygulama içi süre aşımı ve servis kapanışı gibi farklı nedenleri taşımasıdır. ASP.NET Core'un endpoint'e enjekte ettiği token, HttpContext.RequestAborted ile aynıdır; istemci TCP bağlantısını kapattığında tetiklenir. Ancak yalnızca bu token'a dayanmak, bağlı ama yanıt vermeyen istemci için sonsuz bekleme riski yaratır. Bu nedenle her iş akışına açık bir zaman bütçesi ekleyip bağlı token üretin.
app.MapGet("/orders/{customerId:guid}", async (
Guid customerId,
OrdersDbContext db,
CancellationToken requestAborted) =>
{
using var deadline = new CancellationTokenSource(TimeSpan.FromSeconds(2));
using var linked = CancellationTokenSource.CreateLinkedTokenSource(
requestAborted,
deadline.Token);
try
{
var orders = await db.Orders
.AsNoTracking()
.Where(x => x.CustomerId == customerId)
.OrderByDescending(x => x.CreatedAt)
.Take(50)
.ToListAsync(linked.Token);
return TypedResults.Ok(orders);
}
catch (OperationCanceledException) when (deadline.IsCancellationRequested)
{
return TypedResults.StatusCode(StatusCodes.Status504GatewayTimeout);
}
});Bu ayrımın mekanizması önemlidir: requestAborted tetiklenmişse istemci artık yanıtı alamaz ve çoğu durumda yeni bir HTTP yanıtı yazmak anlamsızdır; deadline tetiklenmişse sunucunun kontrollü bir hata üretmesi gerekir. Her OperationCanceledException için 504 dönmek hatalıdır. Ayrıca yanıt gövdesi yazılmaya başlandıysa HttpResponse.HasStarted true olur; bu durumda status code değiştirmek yerine olayı loglayın. csharp eğitimi, csharp kursu, c# eğitimi ve c# kursu içeriklerinde özellikle şu kuralı test edin: bir async metod token kabul ediyorsa, token'ı çağrı zincirindeki bir sonraki I/O operasyonuna iletmelidir.
CPU ağırlıklı kod await içermiyorsa token kendiliğinden işi durdurmaz. Örneğin büyük bir CSV doğrulamasında her 1024 kayıtta ThrowIfCancellationRequested çağrısı yapmak, iptal gecikmesini kayıt başına değil en fazla 1024 iterasyonla sınırlar. Çok sık kontrol ise sıcak döngüde ek dallanma maliyeti doğurur; sınırı gerçek iş birimi ve hedef gecikme ile seçin.
C# Eğitimi: HttpClient çağrılarında çift zaman aşımı tuzağını önlemek
Dış API çağrısında HttpClient.Timeout ile CancellationTokenSource.CancelAfter aynı anda farklı sürelerde kullanılırsa, hangisinin isteği sonlandırdığı belirsizleşir ve ikisi de TaskCanceledException olarak görünebilir. Çağrı başına deadline kullanmak istiyorsanız named veya typed HttpClient üzerinde Timeout değerini InfiniteTimeSpan yapın; sonra çağrı bağlamındaki bağlı token'ı SendAsync metoduna verin. Böylece log kaydı, iptalin istemci kopması mı yoksa sizin tanımladığınız tedarikçi bütçesi mi olduğunu ayırt edebilir.
builder.Services.AddHttpClient<CatalogClient>(client =>
{
client.BaseAddress = new Uri("https://catalog.internal/");
client.Timeout = Timeout.InfiniteTimeSpan;
})
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
PooledConnectionLifetime = TimeSpan.FromMinutes(5),
ConnectTimeout = TimeSpan.FromSeconds(1)
});
public sealed class CatalogClient(HttpClient client)
{
public async Task<CatalogItem?> GetAsync(
string sku,
CancellationToken requestToken)
{
using var vendorDeadline = new CancellationTokenSource(TimeSpan.FromMilliseconds(800));
using var linked = CancellationTokenSource.CreateLinkedTokenSource(
requestToken,
vendorDeadline.Token);
using var request = new HttpRequestMessage(
HttpMethod.Get, $"items/{Uri.EscapeDataString(sku)}");
using var response = await client.SendAsync(
request,
HttpCompletionOption.ResponseHeadersRead,
linked.Token);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<CatalogItem>(
cancellationToken: linked.Token);
}
}HttpCompletionOption.ResponseHeadersRead burada kasıtlıdır: varsayılan davranış gövdenin tamamını buffer'layana kadar SendAsync sonucunu bekletebilir. Büyük JSON yanıtında önce başlıkları alıp gövdeyi token ile deserialize etmek, iptal edilince okumanın durmasına izin verir. Buna karşılık JSON gövdesini başka bir servise aktaracaksanız ReadAsStreamAsync(token) kullanın; stream'i dispose etmemek bağlantının havuza geç dönmesine neden olabilir.
PooledConnectionLifetime değeri yalnızca bağlantı havuzundaki bağlantılar tekrar kullanılırken uygulanır. İç DNS kaydı değişen bir Kubernetes servisinde sonsuz ömürlü bağlantı eski IP'ye tutunabilir. Bu nedenle değer, DNS TTL ve dağıtım stratejisine göre seçilmelidir. Bu ayrıntı, microsoft teknolojileri eğitimi içinde HttpClientFactory anlatılırken sık atlanır: bağlantı havuzunu her istek için yeni HttpClient oluşturarak değil, handler ömrünü kontrollü yenileyerek yönetirsiniz.
Entity Framework Eğitimi: Sorgu iptali ve belirsiz yazma sonuçları
entity framework eğitimi için pratik kural şudur: ToListAsync, SingleOrDefaultAsync, ExecuteUpdateAsync ve SaveChangesAsync çağrılarına aynı bağlı token verilmelidir. SQL Server sağlayıcısı devam eden komutu iptal etmek için sunucuya dikkat paketi gönderebilir, PostgreSQL sağlayıcısı ayrı bir iptal isteği gönderebilir. Yine de iptal çağrısı yapıldıktan sonra veritabanının işlemi hangi noktada bitirdiği uygulama tarafından varsayılamaz; özellikle yazma işlemi ve ağ kopması birlikte yaşanırsa commit gerçekleşmiş olabilir.
public async Task<CreateInvoiceResult> CreateInvoiceAsync(
CreateInvoice command,
CancellationToken cancellationToken)
{
var invoice = new Invoice
{
PublicId = command.IdempotencyKey,
CustomerId = command.CustomerId,
Amount = command.Amount
};
db.Invoices.Add(invoice);
try
{
await db.SaveChangesAsync(cancellationToken);
return new CreateInvoiceResult(invoice.Id, false);
}
catch (DbUpdateException ex) when (IsUniquePublicIdViolation(ex))
{
var existing = await db.Invoices
.AsNoTracking()
.SingleAsync(x => x.PublicId == command.IdempotencyKey,
CancellationToken.None);
return new CreateInvoiceResult(existing.Id, true);
}
}Örnekteki PublicId alanı için veritabanında unique index zorunludur; yalnızca uygulama tarafında önce sorgulayıp sonra eklemek yarış koşulunu çözmez. İstemci iptal ettikten sonra SaveChangesAsync OperationCanceledException fırlatırsa aynı idempotency anahtarıyla yeniden deneme yapılabilir. Yeniden denemede kaydın varlığı, ilk isteğin aslında commit edildiğini gösterir. Kritik ayrıntı: sonucu doğrulamak için CancellationToken.None veya uygulama kapanış token'ından türetilmiş kısa bir token kullanın; zaten iptal edilmiş request token'ını tekrar kullanırsanız doğrulama sorgusu anında iptal olur.
Salt okunur endpoint'lerde AsNoTracking kullanımı tek başına yeterli bir optimizasyon ölçütü değildir. İptal altındaki pahalı sorguyu görmek için EF Core command loglarını etkinleştirin ve CommandExecuted süresini kaydedin. Sorgunun gerçekten sonlanıp sonlanmadığını veritabanı tarafında da kontrol edin: SQL Server için sys.dm_exec_requests, PostgreSQL için pg_stat_activity üzerinden aktif sorgu sayısını test sırasında izleyin.
.NET Core Kursu: İptal akışını ölçmek ve önce-sonra karşılaştırmak
İptal yayılımı bir performans iddiası değil, ölçülebilir bir kaynak geri kazanım davranışıdır. Önce endpoint'in token iletmeyen sürümünü, sonra bağlı token ileten sürümünü aynı yük altında karşılaştırın. k6 ile istekleri istemci tarafında 300 ms sonra iptal ederek p95 süreyi, başarısız istek sayısını ve sunucudaki thread pool kuyruğunu birlikte kaydedin. Yalnız HTTP 5xx oranına bakmak yanıltıcıdır; iptal edilmeyen veritabanı sorguları yanıt dönmese de connection pool slotlarını tüketmeye devam eder.
import http from 'k6/http';
import { sleep } from 'k6';
export const options = {
scenarios: {
cancelled_clients: {
executor: 'constant-vus',
vus: 100,
duration: '60s'
}
}
};
export default function () {
http.get('http://localhost:5000/orders/0f8fad5b-d9cb-469f-a165-70867728950e', {
timeout: '300ms'
});
sleep(0.1);
}Yük testi sürerken uygulama prosesini dotnet-counters ile izleyin:
dotnet-counters monitor --process-id 12345 System.Runtime Çıktıda özellikle threadpool-queue-length, threadpool-thread-count, alloc-rate ve gc-heap-size değerlerini iki koşulda aynı zaman penceresinde kaydedin. Ardından uzun süren bir sorgu için dotnet-trace collect --process-id 12345 --providers Microsoft-DotNETCore-SampleProfiler komutuyla örnekleme izi alın. Token iletilmeyen sürümde çağrı yığını içinde veri sağlayıcısı beklemeleri ve kuyrukta biriken devam işleri daha uzun görünür; düzeltilmiş sürümde iptal edilen işlerin bağlantı ve thread pool kapasitesini ne kadar sürede bıraktığını somut olarak karşılaştırabilirsiniz.blazor eğitimi alan ekipler için aynı ilke Interactive Server bileşenlerinde de geçerlidir: bileşen dispose edildiğinde devam eden HTTP veya EF Core çağrısını iptal edecek bir CancellationTokenSource saklayın. Ancak bir scoped DbContext'i iptal edilmiş çağrıdan sonra yeniden kullanmayın. DbContext eşzamanlı kullanımı desteklemez ve iptal edilen sorgunun sağlayıcı temizliği tamamlanmadan ikinci sorguya geçmek, aralıklı ve zor tekrarlanan hatalara yol açabilir.
İ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 RequestAborted token'ı hangi metodlara iletilmelidir?
Endpoint'ten başlayan her beklemeli I/O çağrısına iletin: EF Core ToListAsync ve SaveChangesAsync, HttpClient SendAsync, Stream.CopyToAsync, ChannelReader.ReadAsync ve Task.Delay buna dahildir. CPU döngülerinde token otomatik çalışmaz; belirlenmiş iş birimi aralığında cancellationToken.ThrowIfCancellationRequested çağırın.
C# kursu projelerinde HttpClient.Timeout yerine CancellationToken kullanmak neden gerekir?
HttpClient.Timeout tek bir client örneğine uygulanır ve farklı çağrıların farklı süre bütçelerini ayırt etmez. Timeout.InfiniteTimeSpan ile global süre aşımını kapatıp her çağrıda CreateLinkedTokenSource kullanmak, istemci kopması ile tedarikçi süre aşımını ayrı loglamayı ve aynı token'ı JSON gövdesi okunurken de kullanmayı sağlar.
Entity Framework eğitimi sırasında SaveChangesAsync iptal edilirse işlem geri alındı mı kabul edilir?
Hayır. İptal sinyali uygulamaya ulaşmadan hemen önce veritabanı commit etmiş olabilir. Oluşturma işlemlerinde veritabanı unique index'iyle korunan bir idempotency anahtarı kullanın. İstemci yeniden denediğinde duplicate key hatasını mevcut kaydı okuyarak başarılı ve tekrar edilmiş sonuç olarak ele alın.
.net core eğitimi için iptal optimizasyonunu hangi araçlarla ölçebilirim?
İstemci tarafında k6 timeout: '300ms' ile kontrollü kopmalar üretin. Sunucuda dotnet-counters monitor --process-id PID System.Runtime ile thread pool ve GC sayaçlarını, dotnet-trace ile örnekleme izlerini alın. Önce token iletmeyen, sonra EF Core ve HttpClient'a bağlı token ileten sürümü aynı VU, süre ve veri setiyle çalıştırın.
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.


