Penjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Error
Batasan kapasitas melindungi API dari kelebihan beban dan penyalahgunaan. Pelajari bagaimana algoritma utama berperilaku, seperti apa respons 429 yang baik, dan bagaimana klien harus mundur, menggunakan simulasi yang kami jalankan.
- Pembatasan tarif membatasi jumlah permintaan yang dapat dibuat klien dalam jangka waktu tertentu.
- ember token memungkinkan ledakan singkat sambil menerapkan tarif rata-rata.
- jendela tetap sederhana dapat melewati dua kali lipat batas pada batas jendela.
- Kembalikan 429 Terlalu Banyak Permintaan dengan header Retry-After, dan suruh klien mundur dengan jitter.
Satu skrip buggy memanggil API Anda dalam loop yang ketat. Tanpa batas, hal ini dapat memperlambat layanan untuk setiap pengguna lain, atau menghabiskan tagihan cloud yang besar. Pembatasan tarif API adalah pagar pembatas yang mencegah satu klien mengambil lebih dari bagian yang wajar.
Untuk menunjukkan bagaimana algoritma umum berperilaku, kami menulis versi kecil Python dan memberinya waktu simulasi permintaan. Output di bawah ini berasal dari proses tersebut. Mereka adalah model pengajaran, bukan kode produksi, dan gateway nyata memiliki lebih banyak fitur.
Apa yang dimaksud dengan pembatasan tarif?
Pembatasan tarif menghitung permintaan per klien dan menolak, atau menunda, permintaan melebihi batas yang disepakati, misalnya 100 permintaan per menit. Gagasan terkait, pembatasan, sering kali berarti memperlambat permintaan daripada menolaknya. kuota biasanya merupakan tunjangan yang lebih besar untuk jangka waktu yang lebih lama, misalnya 10.000 panggilan per bulan dengan paket harga.
Mengapa API membutuhkannya
- Stabilitas: lonjakan lalu lintas tidak dapat membebani database atau layanan hilir.
- Keadilan: satu klien berat tidak dapat membuat klien lainnya kelaparan.
- Keamanan: membatasi memperlambat upaya login dan pengikisan brute force.
- Pengendalian biaya: operasi yang mahal, seperti panggilan model AI, tetap sesuai anggaran.
Pembatasan tingkat adalah kontrol inti dalam 10 Teratas Keamanan API OWASP, dengan konsumsi sumber daya yang tidak dibatasi. Panduan Pengujian API dengan Tukang Pos kami menunjukkan cara mengirim permintaan berulang yang diperlukan untuk memeriksanya.
ember token
Bayangkan sebuah ember yang menampung hingga 5 token. Setiap permintaan membutuhkan token. Token diisi ulang dengan kecepatan 1 per detik, dan ember tidak pernah menampung lebih dari 5. Jika ember kosong, permintaan ditolak.
class TokenBucket:
def __init__(self, capacity, refill_per_sec):
self.capacity = capacity
self.rate = refill_per_sec
self.tokens = capacity
self.last = 0.0
def allow(self, now):
elapsed = now - self.last
self.tokens = min(self.capacity, self.tokens + elapsed * self.rate)
self.last = now
if self.tokens >= 1:
self.tokens -= 1
return True
return False
Kami mengirim 7 permintaan sekaligus, lalu lebih banyak lagi nanti:
burst of 7 at t=0: [True, True, True, True, True, False, False]
t=2.0: [True, True, False]
t=10: 5 allowed of 10
5 yang pertama terjadi sebagai ledakan, lalu embernya kosong. Dua detik kemudian, 2 token telah diisi ulang, jadi 2 permintaan lagi lolos. Setelah jeda yang lama, keranjang kembali penuh tetapi dibatasi pada 5. Perilaku burst-lalu-stabil ini sesuai dengan lalu lintas sebenarnya, itulah sebabnya keranjang token umum digunakan di gateway API. ember bocor adalah kerabat dekat yang memproses permintaan pada tingkat yang tetap, menghaluskan output alih-alih membiarkan ledakan.
Jendela tetap vs jendela geser
Penghitung jendela tetap adalah pendekatan paling sederhana: izinkan 10 permintaan per menit, dan setel ulang penghitung ketika menit berubah. Ia memiliki kelemahan yang diketahui pada batasnya. Kami mengirimkan 10 permintaan dalam 59,9 detik dan 10 permintaan lainnya dalam 60,0 detik, dengan batas 10 per jendela 60 detik:
fixed window allowed around boundary: 20 of 20
sliding log allowed around boundary: 10 of 20
Jendela tetap memungkinkan semua 20 permintaan dalam sepersepuluh detik, dua kali lipat dari kecepatan yang diharapkan, karena permintaan tersebut masuk ke dalam dua jendela berbeda. Sebuah sliding log mengingat waktu setiap permintaan terbaru dan menghitungnya dalam 60 detik terakhir, sehingga hanya mengizinkan 10 detik dengan benar.
Pengorbanannya adalah ingatan. Log geser menyimpan stempel waktu per permintaan. penghitung jendela geser adalah jalan tengah yang populer. Ini memperkirakan laju dengan memadukan jumlah jendela saat ini dan sebelumnya, menggunakan sedikit memori dengan akurasi yang baik.
Perbandingan algoritma
| Algoritma | Meledak | Akurasi | Memori |
|---|---|---|---|
| Memperbaiki jendela | Hingga 2x pada batas | Rendah | Sangat rendah |
| Log geser | Tidak | Tepat | Tinggi |
| Penghitung jendela geser | Kecil | Bagus | Rendah |
| ember token | Diizinkan sesuai kapasitas | Bagus | Rendah |
| Ember bocor | Dihaluskan | Bagus | Rendah |
Apa yang harus dibatasi
- Kunci API atau ID pengguna: opsi paling adil untuk API yang diautentikasi.
- Alamat IP: berguna untuk titik akhir publik, tetapi banyak pengguna dapat berbagi satu IP, dan penyerang dapat merotasinya.
- Titik akhir: operasi yang mahal, seperti penelusuran, ekspor, atau login, memerlukan batasan yang lebih ketat.
- Tingkat paket: pelanggan gratis dan berbayar sering kali mendapatkan batasan yang berbeda.
Titik akhir login memerlukan perhatian khusus. Batasi berdasarkan akun dan IP, sehingga penyerang tidak bisa begitu saja menyebarkan tebakan ke banyak IP atau banyak akun.
Tanggapan 429
Ketika klien melampaui batas, kembalikan HTTP 429 Permintaan Terlalu Banyak, bukan 500 atau 403. Sertakan header yang memberi tahu klien apa yang terjadi dan kapan harus mencoba lagi. Simulasi kami menghasilkan set ini untuk klien tanpa permintaan tersisa:
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 30
Retry-After: 30
Retry-After adalah tajuk HTTP standar. Header RateLimit-* berasal dari draf IETF, dan banyak API menggunakan varian X-RateLimit-* mereka sendiri. Apa pun yang Anda pilih, dokumentasikanlah. Untuk informasi lebih lanjut tentang kode status, lihat lembar contekan kode status HTTP.
Batasan penanganan sebagai klien
Mencoba kembali segera setelah 429 memperburuk keadaan. Jika ribuan klien melakukannya pada saat yang sama, mereka menyerang server dalam gelombang tersinkronisasi. Cara mengatasinya adalah backoff eksponensial dengan jitter: tunggu lebih lama setelah setiap kegagalan, dan tambahkan keacakan.
def backoff(attempt, base=0.5, cap=30, rng=random.Random(4)):
return round(min(cap, base * 2 ** attempt) * rng.random(), 2)
[backoff(a) for a in range(6)]
# [0.12, 0.1, 0.79, 0.62, 0.53, 6.43]
Ini adalah “kegelisahan penuh”: penantian acak antara nol dan batas atas yang tumbuh secara eksponensial. Penantiannya terlihat tidak teratur, dan itulah intinya. Klien menyebar alih-alih mencoba ulang bersama-sama. Kami menyemai generator acak sehingga hasilnya dapat direproduksi.
Daftar periksa klien: patuhi Retry-After jika ada, batasi jumlah percobaan ulang, hanya permintaan percobaan ulang yang aman untuk diulang, dan perhatikan header permintaan yang tersisa sehingga Anda dapat memperlambat sebelum mencapai batas.
Pembatasan tingkat terdistribusi
Dengan beberapa server API di belakang penyeimbang beban, masing-masing server mengandalkan dirinya sendiri sehingga memungkinkan klien melampaui batas dengan menyebarkan permintaan ke server tersebut. Tim biasanya menyimpan penghitung di penyimpanan bersama seperti Redis, dengan operasi atom atau skrip pendek sehingga dua server tidak dapat mengambil token terakhir. Gateway seperti Kong, NGINX, Envoy, dan gateway API cloud menyediakan ini sebagai konfigurasi. Kami tidak menjalankan penyiapan terdistribusi untuk artikel ini.
Batasan kecepatan pengujian
- Kirim permintaan hingga batasnya dan konfirmasikan permintaan tersebut berhasil.
- Kirim satu lagi dan konfirmasikan 429 dengan header yang benar.
- Tunggu waktu reset dan konfirmasi permintaan berhasil lagi.
- Periksa batas per kunci: penggunaan satu klien tidak boleh memblokir yang lain.
- Uji batas antar jendela untuk masalah ledakan ganda.
- Gunakan alat beban, seperti yang dibahas dalam pengujian beban vs pengujian stres, untuk memeriksa perilaku dalam konkurensi berat.
Dalam pengujian unit, masukkan waktu saat ini, seperti yang dilakukan simulasi kami dengan now, sehingga pengujian tidak perlu tidur.
Merancang batasan yang dapat dijalani pengguna
Memilih angka sama pentingnya dengan memilih algoritme. Mulailah dari lalu lintas nyata: lihat berapa banyak permintaan yang dibuat oleh klien sah terberat Anda per menit, dan tetapkan batasan yang nyaman di atas itu. Batasan yang menghalangi penggunaan normal akan menghasilkan tiket dukungan, bukan keamanan.
- Publikasikan batasannya dalam dokumentasi API Anda, per titik akhir dan per paket.
- Peringatkan sebelum memblokir. Header yang menunjukkan permintaan yang tersisa membuat klien yang berperilaku baik memperlambat kecepatannya sendiri.
- Tawarkan alternatif terhadap polling berat, seperti webhook, titik akhir massal, atau halaman yang lebih besar.
- Pantau tarif 429. Kenaikan tiba-tiba dapat berarti serangan, pelepasan klien yang bermasalah, atau batasan yang sekarang terlalu ketat.
- Berikan pengecualian dengan sengaja, misalnya menaikkan batas untuk mitra, dicatat dalam konfigurasi, bukan dalam hardcode.
Putuskan juga apa yang terjadi pada permintaan yang datang melebihi batas. Beberapa API secara singkat mengantri sejumlah kecil permintaan tambahan alih-alih menolaknya, sehingga memperlancar lonjakan singkat. Yang lain memberikan prioritas pada titik akhir yang penting, seperti pembayaran, dibandingkan titik akhir yang kurang penting seperti analitik, sehingga lalu lintas penting tetap mengalir ketika sistem berada di bawah tekanan.
Penutup
Pembatasan tarif yang baik adalah kontrak antara API dan klien. Server memilih algoritma yang adil, biasanya token bucket atau jendela geser, dan menjelaskan batasannya dengan jelas dengan 429 dan Retry-After. Klien menghormati sinyal-sinyal tersebut dan mundur dengan jitter. Mulailah dengan batasan yang besar per kunci API, perhatikan penggunaan sebenarnya, dan kencangkan hanya jika Anda perlu.
Pertanyaan yang sering diajukan
Apa yang dimaksud dengan batasan laju API?
Ini adalah batasan berapa banyak permintaan yang dapat dibuat klien ke API dalam waktu tertentu, misalnya 100 per menit. Permintaan yang melebihi batas ditolak atau ditunda.
Apa yang dimaksud dengan HTTP 429?
429 Terlalu Banyak Permintaan berarti klien telah melampaui batas tarif. Responsnya sering kali menyertakan header Retry-After yang menyatakan berapa lama harus menunggu.
Apa algoritma token bucket?
Setiap permintaan menggunakan token dari ember yang diisi ulang dengan kecepatan tetap hingga maksimum. Ini memungkinkan ledakan singkat sambil menerapkan kecepatan rata-rata.
Apa perbedaan antara pembatasan tarif dan pembatasan?
Pembatasan tarif biasanya menolak permintaan yang melebihi batas. Pembatasan sering kali memperlambat atau malah membuat mereka mengantri. Istilah-istilah ini sering digunakan secara bergantian.
Bagaimana seharusnya klien menangani batasan tarif?
Hormati Coba Ulang-Setelah, coba lagi dengan backoff dan jitter eksponensial, batasi jumlah percobaan ulang, dan perlambat saat permintaan yang tersisa hampir habis.
Teruslah belajar
Butuh bantuan dengan pengujian, WordPress atau SEO?
Kami membantu tim mengirimkan perangkat lunak yang lebih baik dan mengembangkan situs mereka. Beritahu kami apa yang sedang Anda kerjakan dan kami akan menyarankan langkah selanjutnya yang jelas.
Panduan lebih lanjut tentang pengujian, AI & pengembangan modern
Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.
Penjelasan Halusinasi AI: Mengapa Model Bahasa Memperbaiki Masalah dan Cara Menguranginya
Halusinasi AI menjelaskan: apa itu, mengapa model bahasa memproduksinya, tipe umum, cara menguranginya dengan landasan dan petunjuk, dan pemeriksaan…
Baca artikel →DevOpsPenjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar
Variabel lingkungan dijelaskan dengan contoh Python yang kami jalankan: membaca dan mengaturnya, mengapa setiap nilai berupa string, file .env, pewa…
Baca artikel →Pengembangan perangkat lunakPenjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Kesalahan
Pembatasan laju API dijelaskan dengan simulasi yang kami jalankan: keranjang token, jendela tetap, jendela geser, respons 429, header batas laju, pe…
Baca artikel →Otomatisasi pengujianMengejek dengan Python: unittest.mock, patch dan Kesalahan yang Membuat Tes Berbohong
Mengejek dengan Python dengan unittest.mock, menguji: Mock dan return_value, side_effect, menambal di mana nama digunakan, spesifikasi dan autospec,…
Baca artikel →Pengujian perangkat lunakPenjelasan Cakupan Kode: Cakupan Jalur vs Cabang dan Apa Arti 100% Sebenarnya
Cakupan kode dijelaskan dengan coverage.py yang sebenarnya dijalankan: cakupan garis, cabang dan kondisi, membaca laporan, mengapa cakupan 100% masi…
Baca artikel →Basis data & SQLDELETE vs TRUNCATE vs DROP dalam SQL: Perbedaan, Rollback dan Kapan Menggunakan Masing-Masing
DELETE vs TRUNCATE vs DROP dijelaskan dengan SQL yang diuji: apa yang dihapus, rollback, pemicu, reset identitas, kecepatan, dan perbedaan PostgreSQ…
Baca artikel →Basis data & SQLPenjelasan Tampilan SQL: Membuat, Menggunakan, dan Menghindari Kesalahan, Dengan Contoh
Tampilan SQL dijelaskan dengan kueri yang kami jalankan: membuat tampilan, hasil langsung, menyembunyikan kolom, kinerja, tampilan yang dapat diperb…
Baca artikel →Pengembangan perangkat lunakAntarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler
Antarmuka TypeScript vs tipe, diperiksa dengan kompiler sebenarnya: apa yang bisa dilakukan keduanya, apa yang hanya bisa dilakukan satu orang, peng…
Baca artikel →Pengembangan perangkat lunakPenjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas
Python *args dan **kwargs dijelaskan dengan kode yang kami jalankan: pengepakan dan pembongkaran, urutan parameter, argumen hanya kata kunci dan pos…
Baca artikel →Pengembangan perangkat lunakFungsi Python Lambda: Sintaks, Kegunaan Sebenarnya, dan Kapan Tidak Digunakan
Fungsi python lambda dijelaskan dengan kode yang kami jalankan: sintaksis, pengurutan dengan kunci, peta dan filter, penutupan, jebakan pengikatan a…
Baca artikel →Kecerdasan buatanApa Itu Agen AI? Cara Kerjanya, Dengan Agent Loop Sederhana yang Dapat Anda Jalankan
Apa itu agen AI? Panduan sederhana tentang loop agen, alat, memori, dan pagar pembatas, dengan loop Python kecil yang kami jalankan, risiko nyata da…
Baca artikel →DevOpsPemantauan vs Observabilitas: Perbedaan Nyata, Dengan Log, Metrik, dan Jejak
Penjelasan pemantauan vs observabilitas: kegagalan yang diketahui dan tidak diketahui, log, metrik dan jejak, penelusuran insiden checkout, sinyal e…
Baca artikel →DevOpsVolume Docker vs Bind Mounts: Pertahankan Data Kontainer dengan Cara yang Benar
Volume Docker vs pengikatan pengikat dijelaskan: mengapa data kontainer menghilang, volume yang diberi nama, pengikatan pengikatan, tmpfs, contoh Tu…
Baca artikel →Otomatisasi pengujianTDD vs BDD: Perbedaan Utama, Satu Fitur Dibangun dengan Dua Cara dan Kapan Menggunakan Masing-masing
TDD vs BDD dijelaskan dengan satu fitur diskon yang dibuat dengan dua cara: refactor merah-hijau dengan kode yang kami jalankan, skenario Mengingat-…
Baca artikel →Pengembangan perangkat lunakGit merge vs rebase: perbedaan, contoh, dan kapan memakai masing-masing
Git merge vs rebase dijelaskan dengan keluaran log nyata, tabel perbandingan, aturan emas rebase, dan alur kerja tim yang aman.
Baca artikel →Pengembangan perangkat lunakList Comprehension Python: Sintaks, Contoh, dan Kapan Harus Dihindari
List comprehension Python dijelaskan: sintaks, filter, if-else, perulangan bersarang, waktu yang diukur, dan kapan perulangan for biasa lebih baik.
Baca artikel →Basis data & SQLPenjelasan SQL JOIN dengan Contoh (Inner, Left, Right, Full)
Pahami SQL JOIN langkah demi langkah dengan tabel dan query contoh: INNER, LEFT, RIGHT, FULL, CROSS, dan SELF, plus kesalahan umum dan tips performa.
Baca artikel →