7 dk okuma
Giriş
Dağıtık sistemlerde aynı HTTP isteğinin birden fazla kez ulaşması istisna değil, normal bir çalışma koşuludur. Mobil istemci zaman aşımına uğrayabilir, reverse proxy isteği yeniden deneyebilir, mesaj tüketicisi aynı olayı tekrar teslim edebilir veya kullanıcı “Gönder” düğmesine ikinci kez basabilir. Eğer API her isteği yeni bir işlem gibi kabul ederse aynı siparişin iki kez açılması, aynı tahsilatın tekrar denenmesi ya da stok hareketinin çoğalması gibi pahalı sonuçlar ortaya çıkar.
ASP.NET Core API idempotency yaklaşımı, aynı iş niyetini temsil eden tekrar isteklerde yeni bir yan etki üretmek yerine ilk işlemin sonucunu güvenli biçimde yeniden kullanmayı amaçlar. Buradaki kritik nokta yalnızca bir header kontrolü yapmak değildir. Anahtarın doğrulanması, request içeriğinin eşleştirilmesi, veritabanı seviyesinde yarış koşullarının engellenmesi, yanıtın saklanması ve retry davranışının gözlemlenmesi birlikte tasarlanmalıdır.
Idempotency-Key, request hash, SQL Server UNIQUE constraint, eşzamanlı retry ve kayıtlı response akışını .NET 8 üzerinde çalışan örnekle inceleyebilirsiniz.
GitHub Projesini İncele →İçindekiler
- Idempotency neden gereklidir?
- Idempotency-Key sözleşmesini belirleme
- Request hash ile yanlış tekrarları ayırma
- SQL Server UNIQUE kısıtı ile atomik garanti
- İşlem ve yanıt yaşam döngüsü
- Retry ve eşzamanlı istekler
- Observability ve temizlik
Sonuç
Güvenilir Araştırma Kaynakları
1. Idempotency neden gereklidir?
HTTP tarafında istemci bir yanıt alamadığında işlemin sunucuda gerçekleşip gerçekleşmediğini her zaman bilemez. Örneğin sipariş veritabanına yazılmış ancak yanıt ağ üzerinde kaybolmuş olabilir. İstemci aynı POST isteğini tekrar gönderdiğinde sunucu bunu yeni bir sipariş olarak işlerse veri tutarlılığı bozulur. Bu nedenle özellikle ödeme, sipariş, rezervasyon, iade ve stok gibi yan etkili operasyonlarda tekrar denemelerin tasarımın parçası olması gerekir.
Idempotency, “istek yalnızca bir kez gelir” varsayımını ortadan kaldırır. Amaç ağın tam güvenilir olduğunu varsaymak değil; tekrarların güvenli biçimde yönetilebildiği bir uygulama sözleşmesi oluşturmaktır.
2. Idempotency-Key sözleşmesini belirleme
İstemci her yeni iş niyeti için benzersiz bir Idempotency-Key üretir ve aynı işlemi retry ederken aynı anahtarı kullanır. Sunucu anahtarı belirli bir kullanıcı, şirket veya API tüketicisi kapsamıyla birlikte saklamalıdır. Böylece iki farklı müşterinin tesadüfen aynı değeri üretmesi birbiriyle çakışmaz.
Anahtarın formatı, maksimum uzunluğu, geçerlilik süresi ve hangi endpoint’lerde zorunlu olduğu API sözleşmesinde açık olmalıdır. ASP.NET Core tarafında bu kontrol middleware, endpoint filter veya uygulama katmanındaki ortak bir davranış üzerinden uygulanabilir. Tercih edilen nokta, iş kurallarını HTTP ayrıntılarına gereksiz bağlamadan tekrar kullanılabilir bir sınır oluşturmaktır.
3. Request hash ile yanlış tekrarları ayırma
Aynı idempotency anahtarının farklı request gövdeleriyle kullanılması sessizce kabul edilmemelidir. Örneğin ilk istekte ürün A, ikinci istekte ürün B gönderilmişse ikinci çağrı “aynı işlemin tekrarı” değildir. Normalize edilmiş kritik alanlardan üretilen bir request hash değeri idempotency kaydıyla saklanabilir.
Tekrar isteğinde anahtar bulunduğunda hash karşılaştırılır. Hash aynıysa önceki sonuç döndürülür; farklıysa 409 Conflict gibi açık bir sözleşme hatası üretilebilir. Hash yaklaşımında parola, token veya gereksiz kişisel verileri ham biçimde saklamamak önemlidir.
4. SQL Server UNIQUE kısıtı ile atomik garanti
Yalnızca uygulama içinde “önce var mı diye SELECT, sonra INSERT” yapmak yeterli değildir. İki eşzamanlı istek SELECT aşamasında kaydı görmeyip aynı anda işlem başlatabilir. Bu yarış koşulunu kesin biçimde kırmak için veritabanında kapsam + idempotency key üzerinde UNIQUE index veya constraint kullanılmalıdır.
Uygulama INSERT denediğinde yalnızca bir istek kaydı oluşturabilir. Diğer istek unique ihlali aldığında mevcut kaydı okuyup işlem durumuna göre bekleme, yeniden deneme veya kayıtlı sonucu döndürme stratejisine geçer. Böylece koruma tek uygulama instance’ına bağlı kalmaz; birden fazla container veya sunucu aynı veritabanını kullansa da garanti devam eder.
5. İşlem ve yanıt yaşam döngüsü
Idempotency tablosunda yalnızca anahtar değil, durum bilgisi de tutulmalıdır. Örneğin Processing, Completed ve Failed gibi durumlar; request hash, oluşturulma zamanı, HTTP durum kodu ve gerektiğinde response gövdesinin kontrollü bir özeti saklanabilir. Büyük response payload’larını doğrudan tabloya yığmak yerine iş kimliği üzerinden sonucu yeniden oluşturmak bazı sistemlerde daha doğru olabilir.
İş operasyonu ile idempotency kaydının tutarlılığı özellikle önemlidir. Sipariş kaydı commit olmuş fakat idempotency kaydı tamamlanmadan süreç çökmüşse retry davranışı belirsizleşebilir. Bu nedenle transaction sınırı, domain işlemi ve idempotency durum güncellemesi aynı veri kaynağındaysa mümkün olduğunca birlikte ele alınmalıdır.
6. Retry ve eşzamanlı istekler
Retry politikasının görevi başarısız olan her şeyi körlemesine tekrar etmek değildir. Timeout, geçici ağ hatası ve 5xx gibi durumlar ile doğrulama hataları birbirinden ayrılmalıdır. İstemci retry yaptığında aynı Idempotency-Key değerini korumalıdır; yeni anahtar üretirse sunucu bunu yeni iş niyeti olarak görür.
Processing durumundaki aynı anahtara iki istek gelirse sistemin davranışı önceden belirlenmelidir. Kısa süreli bekleme, 409/425 benzeri kontrollü yanıt veya işlem kimliği ile durum sorgulama yaklaşımı kullanılabilir. Burada hedef uzun süre HTTP bağlantısı açık tutmak değil, davranışı deterministik hale getirmektir.
7. Observability ve temizlik
Üretim ortamında idempotency mekanizması görünmez bırakılmamalıdır. Tekrar istek sayısı, unique conflict sayısı, Processing durumunda takılan kayıtlar, ortalama tamamlanma süresi ve hash uyuşmazlıkları ölçülmelidir. Loglarda idempotency anahtarı doğrudan hassas veri taşımıyorsa correlation alanı olarak kullanılabilir; aksi durumda maskelenmiş veya hash’lenmiş temsil tercih edilmelidir.
Kayıtların sonsuza kadar tutulması da gereksiz maliyet oluşturur. İş türüne göre bir retention süresi belirlenmeli ve süresi dolan kayıtlar periyodik olarak temizlenmelidir. Temizlik süresi, istemcilerin gerçek retry penceresinden daha kısa olmamalıdır.
Sonuç
ASP.NET Core API idempotency, tek başına bir header veya cache tekniği değildir. Güvenilir çözüm; istemci sözleşmesi, request hash, SQL Server UNIQUE garantisi, doğru transaction sınırı, kayıtlı yanıt davranışı, kontrollü retry ve observability katmanlarının birlikte çalışmasıyla oluşur.
Özellikle para, stok ve sipariş gibi geri alınması maliyetli yan etkilerde bu desen üretim güvenilirliğini ciddi biçimde artırır. En değerli kazanım ise “aynı istek ikinci kez gelmez” varsayımından kurtulup tekrarların doğal olduğu bir sistem tasarlamaktır.
Güvenilir Araştırma Kaynakları
Microsoft Learn — ASP.NET Core 8 API Reference: https://learn.microsoft.com/dotnet/api/?view=aspnetcore-8.0
Microsoft Learn — What’s new in ASP.NET Core in .NET 8: https://learn.microsoft.com/aspnet/core/release-notes/aspnetcore-8.0
Microsoft Learn — Breaking changes in .NET 8: https://learn.microsoft.com/dotnet/core/compatibility/8.0

