Banyak dari kita berpikir bahwa menggunakan async/await secara otomatis membuat aplikasi kita "skalabel". Tapi kenyataannya, tanpa mekanisme pembatasan (throttling), kode async justru bisa menjadi senjata makan tuan yang menghabiskan resource server dalam sekejap.
Di artikel ini (dan video YouTube terbaru saya), kita akan bahas kenapa Task.WhenAll tanpa limit itu berbahaya dan bagaimana SemaphoreSlim menyelamatkan server kamu.
Masalah: Ilusi Paralelisme yang Tak Terbatas
Bayangkan kamu harus memproses 1.000 data menggunakan API eksternal. Kode yang paling umum ditulis adalah seperti ini:
var tasks = dataList.Select(d => CallExternalApiAsync(d));
await Task.WhenAll(tasks);
Apa yang terjadi di balik layar?
.NET akan mencoba menjalankan 1.000 task tersebut hampir secara bersamaan. Jika setiap task membuka koneksi HTTP atau koneksi database, kamu akan mengalami:
- Socket Exhaustion: Server kehabisan port untuk koneksi keluar.
- Database Pool Starvation: Request lain tertahan karena semua koneksi DB sedang dipakai.
- RAM Spike: Setiap task membawa state machine dan alokasi memori sendiri-sendiri.
Hasilnya? Server "hang", request timeout, dan user kecewa.
Solusi: Memasang "Kran" dengan SemaphoreSlim
SemaphoreSlim adalah cara paling ringan di .NET untuk membatasi berapa banyak task yang boleh berjalan secara konkuren.
Cara Implementasi yang Benar:
// Batasi maksimal 10 operasi konkuren
using var semaphore = new SemaphoreSlim(10);
var tasks = dataList.Select(async d =>
{
await semaphore.WaitAsync(); // Antre di sini
try
{
await CallExternalApiAsync(d);
}
finally
{
semaphore.Release(); // Lepas slot untuk task berikutnya
}
});
await Task.WhenAll(tasks);
Dengan kode ini, meskipun kamu punya 1.000 data, hanya 10 data yang diproses secara bersamaan. Resource server tetap terjaga, dan aplikasi tetap responsif.
3 Hal Penting yang Sering Dilupakan:
-
Gunakan `try...finally
: Jangan pernah lupa memanggilRelease()di blokfinally`. Jika tidak, slot semaphore akan "bocor" dan aplikasi kamu akan mengalami deadlock (berhenti total). - Tentukan Limit yang Rasional: Jangan asal pasang angka. Sesuaikan limit dengan kemampuan resource (misal: jumlah koneksi maksimal di Database Pool kamu).
-
Semaphore vs Lock: Ingat, jangan gunakan
lockbiasa untuk kode async.lockmemblokir thread, sedangkanWaitAsync()membebaskan thread untuk mengerjakan hal lain sambil mengantre.
Kesimpulan
async/await memberikan kita kekuatan, tapi SemaphoreSlim memberikan kita kendali. Jangan biarkan server kamu tumbang hanya karena mencoba melakukan terlalu banyak hal di waktu yang sama.
Top comments (0)