Tidak suka iklan? Pergi Bebas Iklan Hari ini

Pengaturan Batas API — Header, Penurunan Eksponensial, dan Menanggulangi 429

Diperbarui pada

Anda menemukan 429. API sedang mengatakan Anda harus melambat. Berikut cara membaca header X-RateLimit-*, memahami Retry-After, dan menerapkan penurunan eksponensial dengan jitter sehingga integrasi Anda menangani batas kecepatan secara halus alih-alih menyerang server.

Pengaturan Batas Kecepatan API — Header, Backoff Eksponensial, dan Menangani 429 1
IKLAN · HAPUS?

Anda mengalami kode 429. Mungkin handler webhook Anda telah crash. Mungkin batch job Anda diabaikan secara diam-diam. API memberi Anda pesan 'Terlalu Banyak Permintaan' dan sejumlah besar header respons yang mungkin Anda lewatkan saat berpindah.

Header-nya adalah keseluruhan cerita. Berikut cara membacanya, dan cara menulis logika ulang yang tidak memperburuk masalah tersebut.

Header yang Paling Penting

Sebagian besar API yang dibatasi kecepatan mengembalikan beberapa variasi dari header-hal ini pada setiap respons — bukan hanya pada kode 429:

  • X-RateLimit-Limit — jumlah total permintaan yang diizinkan dalam jendela waktu saat ini. API REST GitHub memberi pengguna yang terautentikasi 5.000 permintaan per jam; permintaan tanpa autentikasi mendapat 60.
  • X-RateLimit-Remaining — jumlah permintaan yang tersisa dalam jendela waktu saat ini. Ketika nilai ini mencapai nol, permintaan berikutnya akan mengembalikan kode 429.
  • X-RateLimit-Reset — waktu ketika jendela waktu akan direset, dalam bentuk timestamp Unix. Ini adalah satu-satunya header yang paling sering diabaikan oleh pengembang, dan yang paling berguna.
  • X-RateLimit-Used (khusus untuk GitHub) — jumlah permintaan yang sudah digunakan. Ini mencerminkan Limit - Remaining tetapi berguna untuk pemeriksaan keamanan.
  • Retry-After — hanya muncul pada respons 429. Bisa berupa jumlah detik yang harus ditunggu, atau string tanggal HTTP. Jika API mengirimkannya, gunakan itu — lebih akurat daripada perhitungan yang Anda buat sendiri.

Header respons nyata dari GitHub terlihat seperti ini:

X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4823
X-RateLimit-Reset: 1716998400
X-RateLimit-Used: 177
X-RateLimit-Resource: core

Itu X-RateLimit-Resource header ini khusus untuk GitHub: mereka mempertahankan kolam kuota terpisah untuk REST, pencarian, dan GraphQL. Menggunakan kuota pencarian (dibatasi maksimal 30 permintaan per menit) tidak memengaruhi kuota inti — dan sebaliknya.

Stripe Berbeda

Stripe tidak menggunakan X-RateLimit-* penamaan. Header-nya diprefix dengan cara yang berbeda:

Stripe-Ratelimit-Limit: 100
Stripe-Ratelimit-Remaining: 97
Stripe-Ratelimit-Reset: 1716998460

Dan pada kode 429:

Retry-After: 30

batas default Stripe adalah 100 permintaan dalam mode live per detik, bukan per jam. Ini lebih penting daripada yang terdengar: loop yang mengimpor 500 pelanggan dapat menghabiskan jendela tersebut dalam kurang dari 5 detik jika Anda tidak mengatur batas pada sisi Anda.

Stripe juga membedakan antara batas kecepatan permintaan dan batas spesifik sumber (misalnya, membuat terlalu banyak pelanggan dalam waktu singkat). Isi respons 429 menunjukkan batas mana yang Anda temukan — selalu catat seluruh isi respons, bukan hanya kode status.

Dekode Timestamp Reset

Itu X-RateLimit-Reset nilai adalah timestamp Unix. 1716998400 tidak memberi informasi langsung, tetapi mudah di-dekode: gunakan Konverter Stempel Waktu Unix untuk mengubahnya menjadi waktu yang dapat dibaca dalam waktu UTC dan melihat secara tepat berapa lama waktu resetnya.

Dalam kode: reset_time - time.now() memberikan jumlah detik hingga jendela reset. Tapi periksa X-RateLimit-Remaining terlebih dahulu — jika Anda masih memiliki kuota, tidak perlu menunggu.

Apa yang Diberikan oleh Badan 429

Kode status 429 saja tidak cukup. Isi respons biasanya menunjukkan batas mana yang terpenuhi:

Gambar OG mereka menyertakan judul posting, tanggal, dan waktu membaca

{
  "message": "API rate limit exceeded for user ID 12345.",
  "documentation_url": "https://docs.github.com/rest/overview/rate-limits"
}

Stripe:

{
  "error": {
    "code": "rate_limit",
    "message": "Too many requests hit the API too quickly.",
    "type": "invalid_request_error"
  }
}

OpenAI melanjutkan: pesan kesalahan menunjukkan apakah Anda mencapai batas token per menit atau batas permintaan per menit, yang mengubah strategi retry secara total. Selalu catat seluruh isi respons 429.

Backoff Eksponensial dengan Goyangan

Solusi dasar: tangkap kode 429, tidur selama 1 detik, lalu ulangi. Ini gagal karena dua alasan:

  • Jika Anda memiliki beberapa worker yang mengakses titik akhir yang sama, mereka semua akan tidur selama 1 detik dan mengulang secara bersamaan — sebuah badai retry yang terkoordinasi yang menciptakan masalah yang sama.
  • 1 detik tidak berguna jika Anda telah menghabiskan kuota per jam atau per hari. Anda hanya akan mengumpulkan 3.600 lebih banyak kode 429.

Pendekatan yang benar adalah backoff eksponensial dengan goyangan: setiap retry menunggu lebih lama dari yang sebelumnya, dengan komponen acak untuk memisahkan worker yang berjalan secara bersamaan.

import time
import random
import requests

def fetch_with_backoff(url, headers, max_retries=5):
    base_delay = 1  # seconds

    for attempt in range(max_retries):
        response = requests.get(url, headers=headers)

        if response.status_code != 429:
            return response

        # Prefer Retry-After if the API provides it
        retry_after = response.headers.get("Retry-After")
        if retry_after:
            wait = int(retry_after)
        else:
            # Fall back to X-RateLimit-Reset
            reset = response.headers.get("X-RateLimit-Reset")
            if reset:
                wait = max(0, int(reset) - int(time.time()))
            else:
                # Pure exponential backoff with full jitter
                cap = 60  # max wait: 60s
                wait = random.uniform(0, min(cap, base_delay * (2 ** attempt)))

        print(f"Rate limited. Attempt {attempt + 1}/{max_retries}. Waiting {wait:.1f}s")
        time.sleep(wait)

    raise Exception(f"Max retries exceeded after {max_retries} attempts")

Urutan prioritas dalam implementasi ini adalah sengaja:

  • Retry-After pertama — jika API memberi tahu Anda secara eksplisit berapa lama harus menunggu, gunakan itu. Jangan menghitung ulang dengan perhitungan Anda sendiri.
  • X-RateLimit-Reset sebagai fallback — hitung detik aktual hingga reset, bukan menebak jeda tetap.
  • Goyangan penuh sebagai solusi terakhirrandom.uniform(0, cap) membagikan retry di seluruh jendela backoff. Blog arsitektur AWS menjelaskan ini sebagai "goyangan penuh" dan menunjukkan bahwa ini secara signifikan mengurangi kolisi di sisi server dibandingkan dengan goyangan sama atau tidak ada goyangan sama sekali.
  • max(0, ...) pada reset — timestamp reset bisa berada di masa lalu saat Anda melakukan perhitungan. Perlindungan terhadap nilai tidur negatif yang membuat handler Anda crash.

Kesalahan Umum

Menganggap kesalahan bukan 429 sebagai kesalahan batas kecepatan. Kode 503 adalah kesalahan server. Kode 401 berarti kredensial Anda salah. Periksa status_code == 429 secara eksplisit sebelum menerapkan logika retry batas kecepatan.

Mengabaikan kode 429 dan mengembalikan data kosong. Kegagalan diam lebih sulit diperbaiki daripada pengecualian yang diangkat. Tampilkan kesalahan tersebut.

Menggunakan jeda tetap. Jika Anda telah menghabiskan jendela per jam dengan 47 menit tersisa, tidur selama 5 detik tidak memberi manfaat apa pun. Hitung dari timestamp reset.

Mengulang tanpa batas. Atur max_retries batasi dan tingkatkan setelah kehabisan. Beberapa kode 429 menunjukkan kehabisan kuota yang tidak akan pulih sampai periode pembayaran berikutnya — ulang tanpa batas adalah bug.

Tidak memantau X-RateLimit-Remaining secara proaktif. Jika Remaining turun di bawah 10% dari Limit, mulai memisahkan permintaan sebelum mencapai nol. Sebagian besar SDK tidak melakukannya secara otomatis. Biaya adalah beberapa milidetik tambahan latency; manfaatnya adalah tidak pernah melihat kode 429 pada awalnya.

Kesimpulan

Kode 429 bukan masalah satu kali yang bisa diperbaiki dan dilupakan. Ini adalah kendala berulang, dan mengabaikan header yang disediakan berarti Anda akan terus menghadapi dinding yang sama. Gunakan Retry-After ketika API menyediakannya. Hitung dari X-RateLimit-Reset ketika tidak disediakan. Tambahkan goyangan agar retry tidak terkoordinasi. Tetapkan batas agar ulang tanpa batas tidak menjadi insiden produksi.

Dan ketika Anda memandang X-RateLimit-Reset: 1716998400 dan bertanya-tanya kapan itu sebenarnya terjadi — Konverter Stempel Waktu Unix akan memberi tahu Anda dalam satu klik.

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?