ASP.NET Core eğitimi kapsamında istek zaman bütçesini TimeProvider, iptal belirteçleri ve FakeTimeProvider ile ele alıyoruz. HTTP, veritabanı ve test katmanlarında aynı deadline bilgisini taşıyan uygulanabilir bir tasarım kuruyoruz.
ASP.NET Core Eğitimi: TimeProvider ile Test Edilebilir Zaman Bütçesi
ASP.NET Core eğitimi ile istek deadline sözleşmesi kurmak
Bir isteğe sabit bir timeout vermek yerine mutlak bir deadline taşıyın. Sabit timeout, API gateway'de harcanan süreyi hesaba katmaz: gateway 1.8 saniye bekledikten sonra uygulamanıza gelen ve 2 saniyelik yeni timeout alan istek, çağrı zincirinin toplam bütçesini aşar. Bu .net core eğitimi örneğinde istemciden gelen X-Deadline-UnixMs üst bilgisini doğruluyor, en fazla 5 saniyelik sunucu sınırı uyguluyor ve üretilen token'ı HttpContext.Items üzerinden endpoint'e aktarıyoruz.
public sealed class DeadlineMiddleware
{
private static readonly object TokenKey = new();
private readonly RequestDelegate _next;
private readonly TimeProvider _clock;
public DeadlineMiddleware(RequestDelegate next, TimeProvider clock)
{
_next = next;
_clock = clock;
}
public async Task InvokeAsync(HttpContext context)
{
var now = _clock.GetUtcNow();
var maximum = TimeSpan.FromSeconds(5);
var requested = ReadDeadline(context.Request.Headers, now, maximum);
var remaining = requested - now;
if (remaining <= TimeSpan.Zero)
{
context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
return;
}
using var deadlineCts = new CancellationTokenSource(remaining, _clock);
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
context.RequestAborted, deadlineCts.Token);
context.Items[TokenKey] = linkedCts.Token;
context.Items[typeof(DateTimeOffset)] = requested;
await _next(context);
}
private static DateTimeOffset ReadDeadline(
IHeaderDictionary headers, DateTimeOffset now, TimeSpan maximum)
{
if (long.TryParse(headers["X-Deadline-UnixMs"], out var unixMs))
{
var clientDeadline = DateTimeOffset.FromUnixTimeMilliseconds(unixMs);
if (clientDeadline > now && clientDeadline - now <= maximum)
return clientDeadline;
}
return now + maximum;
}
}Kayıt sırasında middleware'i app.UseMiddleware<DeadlineMiddleware>() ile route eşlemesinden önce yerleştirin. Endpoint tarafında Items erişimini tek bir extension içine alın ve token yoksa RequestAborted'a düşün. Yaygın hata, yalnızca RequestAborted kullanmaktır; bu token çoğunlukla bağlantı kapanana kadar iptal olmaz ve bağlantısı açık kalan yavaş istemcilerde veritabanı sorgunuz gereksiz yere çalışmaya devam eder. csharp eğitimi veya c# eğitimi içeriğinde özellikle vurgulanması gereken ayrıntı, istemcinin gönderdiği deadline değerinin güvenilir kabul edilmemesidir: middleware hem geçmiş zamanı hem de sunucunun izin verdiği üst sınırı kontrol etmelidir.
c# kursu projelerinde HttpClient ile deadline yayılımı
Downstream HTTP çağrısına yeni bir 30 saniyelik timeout vermek yerine kalan bütçeyi iletin. Bunun için typed HttpClient'a bir DelegatingHandler ekleyin. Handler, kalan süre sıfırsa soket açmadan OperationCanceledException üretir; kalan süre varsa hem X-Deadline-UnixMs üst bilgisini ekler hem de SendAsync çağrısını bu deadline token'ı ile iptal eder. Böylece upstream'in 3 saniyelik bütçesi varsa, ikinci servis çağrısı bağımsız 30 saniye bekleyemez.
public sealed class DeadlinePropagationHandler : DelegatingHandler
{
private readonly TimeProvider _clock;
private readonly IHttpContextAccessor _httpContextAccessor;
public DeadlinePropagationHandler(
TimeProvider clock,
IHttpContextAccessor httpContextAccessor)
{
_clock = clock;
_httpContextAccessor = httpContextAccessor;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var context = _httpContextAccessor.HttpContext;
var deadline = context?.Items[typeof(DateTimeOffset)] as DateTimeOffset?;
if (deadline is null)
return await base.SendAsync(request, cancellationToken);
var remaining = deadline.Value - _clock.GetUtcNow();
if (remaining <= TimeSpan.Zero)
throw new OperationCanceledException("Request deadline elapsed.");
request.Headers.Remove("X-Deadline-UnixMs");
request.Headers.Add("X-Deadline-UnixMs", deadline.Value.ToUnixTimeMilliseconds().ToString());
using var budgetCts = new CancellationTokenSource(remaining, _clock);
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
cancellationToken, budgetCts.Token);
return await base.SendAsync(request, linkedCts.Token);
}
}
builder.Services.AddHttpContextAccessor();
builder.Services.AddSingleton(TimeProvider.System);
builder.Services.AddTransient<DeadlinePropagationHandler>();
builder.Services.AddHttpClient<CatalogClient>(client =>
{
client.Timeout = Timeout.InfiniteTimeSpan;
}).AddHttpMessageHandler<DeadlinePropagationHandler>();Buradaki Timeout.InfiniteTimeSpan bilinçli bir seçimdir. HttpClient.Timeout ile handler'ın ürettiği token aynı çağrıda yarışırsa loglarda hangi sınırın isteği iptal ettiği belirsizleşir ve TimeoutException ile OperationCanceledException sınıflandırmanız tutarsız olur. Tek timeout otoritesi deadline token'ı olmalıdır. Bir csharp kursu laboratuvarında bunu kanıtlamak için downstream endpoint'ine Task.Delay(2000, cancellationToken) ekleyin, upstream deadline'ını 500 ms yapın ve downstream uygulamasında isteğin yaklaşık 500 ms civarında iptal edildiğini ölçün.
Entity Framework eğitimi: sorgu iptalini gerçek zaman bütçesine bağlamak
Entity Framework eğitimi sırasında sık görülen hata, controller token'ını EF Core çağrısına vermemektir. LINQ sorgusu oluşturulurken token gerekmez; token ancak ToListAsync, SingleAsync, ExecuteUpdateAsync veya SaveChangesAsync gibi veritabanına komut gönderen async noktada verilmelidir. SQL Server sağlayıcısında iptal, uygun koşullarda TDS ATTENTION paketiyle sunucuya iletilir; token verilmezse uygulama HTTP 408 dönse bile sorgu bağlantı havuzundaki oturumu meşgul etmeyi sürdürebilir.
app.MapGet("/orders/{customerId:guid}", async (
Guid customerId,
OrdersDbContext db,
HttpContext httpContext) =>
{
var deadlineToken = httpContext.Items[DeadlineMiddlewareToken.Key] as CancellationToken?
?? httpContext.RequestAborted;
var orders = await db.Orders
.AsNoTracking()
.Where(x => x.CustomerId == customerId)
.OrderByDescending(x => x.CreatedAt)
.Take(100)
.Select(x => new OrderListItem(x.Id, x.CreatedAt, x.Total))
.ToListAsync(deadlineToken);
return Results.Ok(orders);
});DbCommand.CommandTimeout ile CancellationToken aynı mekanizma değildir. CommandTimeout, sağlayıcının komut seviyesindeki saniye tabanlı sınırıdır; deadline ise istek zincirinin milisaniye hassasiyetli toplam bütçesidir. Her istek için context.Database.SetCommandTimeout ile global değeri değiştirmek, özellikle DbContext pooling kullanan kodda taşınan state nedeniyle dikkat gerektirir. Pratik yaklaşım, sorguya deadline token'ını her zaman geçirmek ve veritabanı için ayrıca makul bir üst sınır tanımlamaktır. .net core kursu katılımcıları için doğrulama adımı olarak SQL Server'da Extended Events ile attention olaylarını, PostgreSQL'de ise pg_stat_activity içindeki bekleyen sorguları izleyin; HTTP iptalinden sonra sorgunun gerçekten sonlandığını böyle doğrulayabilirsiniz.
Blazor eğitimi ve API testlerinde FakeTimeProvider kullanımı
Gerçek Task.Delay kullanan timeout testleri yavaştır ve CI makinesinin zamanlayıcısına bağlı olarak kararsızlaşır. Microsoft.Extensions.TimeProvider.Testing paketindeki FakeTimeProvider ile zamanı ileri alıp deadline davranışını milisaniye beklemeden doğrulayın. Bu yöntem yalnızca kodunuz TimeProvider alan Task.Delay veya CancellationTokenSource overload'larını kullandığında çalışır; DateTimeOffset.UtcNow ve doğrudan Task.Delay(TimeSpan) çağrıları sahte saatten etkilenmez.
using Microsoft.Extensions.Time.Testing;
[Fact]
public async Task Deadline_gecmisse_http_cagrisi_baslatilmaz()
{
var clock = new FakeTimeProvider(DateTimeOffset.Parse("2026-01-01T10:00:00Z"));
var deadline = clock.GetUtcNow() + TimeSpan.FromMilliseconds(250);
using var cts = new CancellationTokenSource(deadline - clock.GetUtcNow(), clock);
var operation = Task.Delay(TimeSpan.FromSeconds(10), clock, cts.Token);
clock.Advance(TimeSpan.FromMilliseconds(251));
await Assert.ThrowsAnyAsync<OperationCanceledException>(
async () => await operation);
}blazor eğitimi örneklerinde aynı soyutlama, arama kutusu debounce işlemlerini test etmek için kullanılabilir. Ancak Blazor WebAssembly'de tarayıcının fetch iptalini ve JavaScript timer'larını FakeTimeProvider ile kontrol edemezsiniz; test edilen şey .NET tarafındaki planlama kodudur. microsoft teknolojileri eğitimi kapsamında API, worker ve UI projelerinin hepsine TimeProvider enjekte edilirse, zaman davranışı testlerde aynı araçla denetlenir. Bu tasarımın küçük ama önemli faydası, UTC hesaplarını tek yerde tutmasıdır: yerel saat geçişleri ve daylight saving değişimleri deadline hesabına karışmaz.
Önce-sonra ölçümü: timeout maliyetini dotnet-counters ve k6 ile görmek
Bu değişikliği performans iyileştirmesi olarak kabul etmeden önce iki koşuyu aynı yükte karşılaştırın. İlk koşuda downstream çağrısında yalnızca varsayılan HttpClient timeout'u kalsın. İkinci koşuda DeadlineMiddleware, DeadlinePropagationHandler ve EF Core token aktarımını etkinleştirin. Her iki koşuda da downstream servisi isteklerin yüzde 20'sinde 2 saniye gecikme üretsin; upstream deadline'ı 500 ms olsun. Amaç ortalama gecikmeyi değil, deadline sonrası açık kalan iş sayısını ve kaynak basıncını ölçmektir.
import http from 'k6/http';
import { check } from 'k6';
export const options = {
vus: 80,
duration: '60s'
};
export default function () {
const response = http.get('http://localhost:5000/api/catalog', {
headers: { 'X-Deadline-UnixMs': `${Date.now() + 500}` }
});
check(response, {
'deadline respected': r => r.status === 200 || r.status === 408 || r.status === 499
});
}Yük testi sırasında uygulama PID'si için dotnet-counters monitor --process-id <PID> System.Runtime komutunu çalıştırın. ThreadPool Queue Length, Working Set, Allocation Rate ve yüzde 99 gecikmesini k6 çıktısıyla birlikte kaydedin. Sonra dotnet-trace collect --process-id <PID> ile timeout anında iz alın; iptal sonrası bekleyen Task'ların, socket receive işlemlerinin veya EF komutlarının kalıp kalmadığını analiz edin. Beklenen önce-sonra farkı şudur: ikinci koşuda timeout dönen isteklerin downstream'de daha kısa ömürlü olması nedeniyle ThreadPool kuyruğu ve eşzamanlı açık bağlantı sayısı düşmelidir. Bu değerler değişmiyorsa token bir katmanda yutuluyor, örneğin repository içindeki ToListAsync çağrısına aktarılmıyor olabilir.
İ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çin RequestAborted yeterli mi?
Hayır. RequestAborted genellikle istemci bağlantıyı kapattığında iptal olur. Sunucu tarafı süre sınırı için CancellationTokenSource(remaining, TimeProvider) oluşturun, ardından bunu RequestAborted ile CreateLinkedTokenSource üzerinden birleştirin. EF Core ve HttpClient çağrılarına birleşik token'ı açıkça geçin.
c# eğitimi sırasında HttpClient.Timeout neden InfiniteTimeSpan yapılır?
Deadline token'ı zaten kalan istek bütçesini uygular. HttpClient.Timeout da aktif kalırsa iki farklı zamanlayıcı yarışır ve iptal nedenini ayırmak zorlaşır. Typed HttpClient yapılandırmasında client.Timeout = Timeout.InfiniteTimeSpan kullanın, sonra her SendAsync çağrısına deadline token'ını verin.
entity framework eğitimi projelerinde CancellationToken SQL sorgusunu kesin durdurur mu?
Token'ı ToListAsync, SaveChangesAsync veya ExecuteUpdateAsync çağrısına vermek sağlayıcının iptal protokolünü tetikler, ancak ağ kesintisi veya sağlayıcı davranışı nedeniyle anlık sonlanma garantisi değildir. SQL Server için Extended Events attention olaylarıyla, PostgreSQL için pg_stat_activity ile iptal edilen sorgunun sunucuda kapandığını doğrulayın.
blazor eğitimi testlerinde FakeTimeProvider tarayıcı timer'larını kontrol eder mi?
Hayır. FakeTimeProvider, TimeProvider kullanan .NET kodunu kontrol eder. Blazor WebAssembly tarafındaki JavaScript setTimeout veya fetch davranışı için tarayıcı test araçları gerekir. Debounce mantığını TimeProvider ile yazıp birim testte FakeTimeProvider.Advance kullanmak, .NET katmanını deterministik hale getirir.
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.


