Uji bagaimana aplikasi Anda menangani batas laju API GitHub

Tip

Baru mengenal throttling? Pelajari apa itu throttling dan cara menanganinya.

Sekilas
Tujuan: Menguji cara aplikasi Anda menangani batas laju REST API GitHub
Waktu: 15 menit
Plugins:RateLimitingPlugin, GenericRandomErrorPlugin, RetryAfterPlugin
Prasyarat:Menyiapkan Proksi Dev

Aplikasi Anda memanggil API GitHub. Ini berfungsi pada komputer Anda, kemudian job CI, organisasi besar, atau hari yang sibuk mendorongnya melebihi batas laju, dan mulai gagal. Untuk mengujinya terhadap API nyata, Anda harus menghabiskan batas permintaan API Anda, lalu menunggu hingga satu jam sebelum Anda dapat mencoba lagi. Dev Proxy mensimulasikan batas laju GitHub secara lokal, dengan batas dan jendela waktu yang Anda pilih.

Ketahui apa yang dikembalikan GitHub

GitHub memiliki 2 jenis batas laju untuk REST API.

Batas permintaan primer membatasi berapa banyak permintaan yang Anda buat per jam. Misalnya, 60 untuk permintaan yang tidak diautentikasi dan 5.000 untuk permintaan dengan token akses pribadi. Setiap respons menyertakan header yang menunjukkan di mana Anda berada:

Header Meaning
x-ratelimit-limit Jumlah maksimum permintaan per jam
x-ratelimit-remaining Jumlah permintaan yang tersisa di jendela saat ini
x-ratelimit-reset Waktu ketika jendela direset, dalam detik epoch UTC

Ketika Anda melebihi batas utama, GitHub mengembalikan 403 atau 429 dengan x-ratelimit-remaining diatur ke 0. Jangan coba lagi sampai waktu yang tercantum di x-ratelimit-reset.

batas rate sekunder melindungi GitHub dari lonjakan, seperti terlalu banyak permintaan bersamaan atau membuat terlalu banyak konten terlalu cepat. Ketika Anda melewati salah satunya, GitHub mengembalikan 403 atau 429 dengan pesan tentang batas laju sekunder. Jika respons memiliki header retry-after, tunggu selama jumlah detik tersebut. Jika tidak, tunggu setidaknya satu menit, dan tingkatkan waktu tunggu jika permintaan terus gagal.

GitHub dapat melarang integrasi yang terus mengirim permintaan saat terkena pembatasan laju. Untuk informasi selengkapnya, lihat Batas permintaan untuk REST API dalam dokumentasi GitHub.

Mensimulasikan batas laju utama

Gunakan RateLimitingPlugin untuk menghitung permintaan dan mengembalikan header batas laju GitHub. Untuk menguji tanpa menunggu satu jam, gunakan batas kecil dan jendela pendek.

Berkas: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "RetryAfterPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
    },
    {
      "name": "RateLimitingPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "githubRateLimit"
    }
  ],
  "urlsToWatch": [
    "https://api.github.com/*"
  ],
  "githubRateLimit": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/ratelimitingplugin.schema.json",
    "headerLimit": "x-ratelimit-limit",
    "headerRemaining": "x-ratelimit-remaining",
    "headerReset": "x-ratelimit-reset",
    "resetFormat": "UtcEpochSeconds",
    "costPerRequest": 1,
    "rateLimit": 5,
    "resetTimeWindowSeconds": 60,
    "warningThresholdPercent": 0,
    "whenLimitExceeded": "Custom",
    "customResponseFile": "github-rate-limit-exceeded.json"
  }
}

Caution

RetryAfterPlugin Tambahkan sebelum RateLimitingPlugin dalam file konfigurasi Anda. Jika Anda menambahkannya setelah, RateLimitingPlugin menangani permintaan sebelum RetryAfterPlugin dapat memeriksanya.

Dalam file respons kustom, tentukan respons yang GitHub kembalikan saat Anda melebihi batas laju utama.

Berkas: github-rate-limit-exceeded.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/ratelimitingplugin.customresponsefile.schema.json",
  "statusCode": 429,
  "headers": [
    {
      "name": "content-type",
      "value": "application/json; charset=utf-8"
    }
  ],
  "body": {
    "message": "API rate limit exceeded for user ID 1.",
    "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api"
  }
}

Mulai Dev Proxy dan jalankan aplikasi Anda.

devproxy --config-file devproxyrc.json

Dev Proxy meneruskan 5 permintaan pertama dalam setiap menit ke GitHub dan mengatur x-ratelimit-* header pada respons. Dari permintaan ke-6, Dev Proxy mengembalikan respons batas laju dengan x-ratelimit-remaining diatur ke 0 dan x-ratelimit-reset diatur ke akhir jendela. Jika aplikasi Anda memanggil API lagi sebelum jendela diatur ulang, RetryAfterPlugin melaporkannya dan membatasi permintaan.

Periksa apakah aplikasi Anda:

  • x-ratelimit-remaining mendeteksi dan melambat sebelum mencapai 0.
  • Berhenti memanggil API setelah respons batas permintaan dan menunggu hingga x-ratelimit-reset.
  • Memberi tahu pengguna apa yang terjadi, misalnya "batas laju GitHub tercapai, mencoba kembali pada pukul 14:05", alih-alih gagal diam-diam.

Note

GitHub mengembalikan salah satu 403 atau 429 saat Anda melebihi batas permintaan. Untuk menguji bahwa aplikasi Anda juga menangani 403 , ubah statusCode ke 403. RetryAfterPlugin hanya melacak respons 429, sehingga tidak melaporkan percobaan ulang awal setelah 403.

Tip

Dev Proxy meneruskan permintaan ke GitHub hingga batas simulasi tercapai. Permintaan ini juga akan dihitung ke batas rate limit GitHub Anda.

Mensimulasikan batas laju sekunder

Batas laju sekunder terjadi secara tiba-tiba dan menyertakan header retry-after. Gunakan GenericRandomErrorPlugin untuk mengembalikannya secara acak.

Berkas: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "RetryAfterPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll"
    },
    {
      "name": "GenericRandomErrorPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "githubSecondaryRateLimit"
    }
  ],
  "urlsToWatch": [
    "https://api.github.com/*"
  ],
  "githubSecondaryRateLimit": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.schema.json",
    "errorsFile": "github-secondary-rate-limit.json",
    "rate": 50,
    "retryAfterInSeconds": 60
  }
}

File: github-secondary-rate-limit.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.github.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "content-type",
              "value": "application/json; charset=utf-8"
            },
            {
              "name": "retry-after",
              "value": "@dynamic"
            }
          ],
          "body": {
            "message": "You have exceeded a secondary rate limit. Please wait a few minutes before you try again.",
            "documentation_url": "https://docs.github.com/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits"
          }
        }
      ]
    }
  ]
}

Mulai Dev Proxy dan jalankan aplikasi Anda. Pastikan aplikasi Anda menunggu jumlah detik yang tercantum pada header retry-after sebelum memanggil API lagi. Jika tidak, RetryAfterPlugin melaporkannya.

Jika Anda menggunakan Octokit dengan plugin pembatasan, periksa apakah handler onSecondaryRateLimit dan onRateLimit Anda berjalan dan mengembalikan hasil yang Anda harapkan.

Langkah selanjutnya

Pelajari selengkapnya tentang RateLimitingPlugin.

Baca juga