Uji retry dan time-out di aplikasi .NET yang menggunakan Microsoft.Extensions.Http.Resilience

Tip

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

Sekilas
Tujuan: Konfirmasikan bahwa handler ketahanan HTTP .NET Anda mencoba kembali, melakukan backoff, dan mengalami time-out seperti yang diharapkan
Waktu: 15 menit
Plugins:GenericRandomErrorPlugin, RetryAfterPlugin, LatencyPlugin
Prasyarat:Siapkan Dev Proxy, aplikasi .NET yang menggunakan Microsoft.Extensions.Http.Resilience

Anda menambahkan AddStandardResilienceHandler() ke HttpClient. Bagaimana kamu tahu bahwa ini berfungsi? API yang Anda panggil jarang gagal sesuai permintaan, dan pengujian unit yang mem-mock HttpMessageHandler melewati pipeline resiliensi yang ingin Anda uji.

Dev Proxy berada di antara aplikasi Anda dan API. Ini mengembalikan kesalahan dan respons lambat ke aplikasi Anda, sehingga aplikasi Anda berjalan tidak berubah dan handler ketahanan bereaksi terhadap respons HTTP nyata. Anda melihat setiap upaya dalam output Dev Proxy.

Fungsi handler resilience standar

Sebelum Anda menguji, ketahui apa yang dapat Anda harapkan. Dengan opsi default, AddStandardResilienceHandler():

Behavior Default
Coba ulang aktif HTTP 500 ke atas, 408, 429, HttpRequestException, dan TimeoutRejectedException
Jumlah percobaan ulang 3, dengan backoff eksponensial dan jitter, mulai dari 2 detik
Retry-After tajuk Terhormat. Handler menunggu selama waktu yang diminta API.
Batas waktu percobaan 10 detik per upaya
Total waktu habis 30 detik untuk permintaan, termasuk semua percobaan ulang

Untuk daftar lengkap strategi dan defaultnya, lihat Default penangan ketahanan standar.

Arahkan aplikasi Anda melalui Dev Proxy

.NET menggunakan proksi sistem, jadi saat Anda memulai Dev Proxy, proksi tersebut mencegat permintaan aplikasi Anda tanpa perubahan kode. Untuk informasi selengkapnya, lihat Menggunakan Dev Proxy dengan aplikasi .NET.

Simulasikan error transien

Buat konfigurasi Dev Proxy yang membuat permintaan ke API Anda gagal dengan kesalahan yang ditangani dengan percobaan ulang oleh handler. Contoh ini menggunakan https://api.contoso.com. Ganti dengan URL API yang dipanggil aplikasi Anda.

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": "transientErrors"
    }
  ],
  "urlsToWatch": [
    "https://api.contoso.com/*"
  ],
  "transientErrors": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.schema.json",
    "errorsFile": "transient-errors.json",
    "rate": 50
  }
}

Caution

RetryAfterPlugin Tambahkan sebelum GenericRandomErrorPlugin dalam file konfigurasi Anda. Jika Anda menambahkannya setelahnya, GenericRandomErrorPlugin menggagalkan permintaan sebelum RetryAfterPlugin dapat memeriksanya.

Dalam file error, tentukan respons throttling dan dua kesalahan server. Nilai @dynamic mengatur Retry-After header dan memberi tahu RetryAfterPlugin untuk memeriksa apakah aplikasi Anda menunggu selama itu sebelum memanggil API lagi.

Berkas: transient-errors.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/genericrandomerrorplugin.errorsfile.schema.json",
  "errors": [
    {
      "request": {
        "url": "https://api.contoso.com/*"
      },
      "responses": [
        {
          "statusCode": 429,
          "headers": [
            {
              "name": "Retry-After",
              "value": "@dynamic"
            }
          ]
        },
        {
          "statusCode": 500
        },
        {
          "statusCode": 503
        }
      ]
    }
  ]
}

Mulai Dev Proxy dan jalankan aplikasi Anda.

devproxy --config-file devproxyrc.json

Dengan tingkat kegagalan 50%, sebagian besar permintaan pulih setelah satu atau dua percobaan ulang. Dalam output Dev Proxy, periksa apakah:

  • Setelah respons 429, upaya berikutnya ke URL yang sama dilakukan setelah waktu Retry-After tersebut. Dev Proxy menggunakan 5 detik secara default. Jika aplikasi Anda memanggil API terlalu dini, RetryAfterPlugin melaporkannya dan membatasi permintaan.
  • Aplikasi Anda tidak mengirim lebih banyak upaya daripada yang Anda konfigurasi.
  • Permintaan yang tidak ingin Anda coba lagi, seperti POST yang membuat record data, dikirim hanya sekali. Untuk mengecualikannya, panggil options.Retry.DisableForUnsafeHttpMethods() atau options.Retry.DisableFor(...).

Lihat apa yang terjadi saat percobaan kembali habis

Percobaan ulang menyembunyikan kegagalan singkat. Anda juga perlu mengetahui apa yang dilakukan aplikasi Anda saat API terus gagal. Mulai Proksi Dev dengan tingkat kegagalan 100%:

devproxy --config-file devproxyrc.json --failure-rate 100

Dev Proxy menunjukkan 4 upaya untuk setiap permintaan: permintaan asli dan 3 percobaan ulang. Setelah percobaan ulang terakhir, handler standar tidak memunculkan pengecualian. Ini mengembalikan respons kesalahan terakhir ke kode Anda. Periksa apa yang dilakukan aplikasi Anda dengannya. Misalnya, EnsureSuccessStatusCode() melempar HttpRequestException, dan GetStringAsync() melempar juga. Pastikan aplikasi Anda menampilkan pesan yang berguna atau menggunakan alternatif, alih-alih mengalami crash atau menampilkan kesalahan umum.

Timeout pengujian

API yang lambat memicu jalur yang berbeda di handler. Untuk mengujinya, gunakan LatencyPlugin untuk menunda respons di luar batas waktu upaya 10 detik.

Berkas: devproxyrc.json

{
  "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/rc.schema.json",
  "plugins": [
    {
      "name": "LatencyPlugin",
      "enabled": true,
      "pluginPath": "~appFolder/plugins/DevProxy.Plugins.dll",
      "configSection": "slowApi"
    }
  ],
  "urlsToWatch": [
    "https://api.contoso.com/*"
  ],
  "slowApi": {
    "$schema": "https://raw.githubusercontent.com/dotnet/dev-proxy/main/schemas/v3.3.1/latencyplugin.schema.json",
    "minMs": 11000,
    "maxMs": 15000
  }
}

Mulai Dev Proxy dan jalankan aplikasi Anda. Setiap upaya membutuhkan waktu lebih dari 10 detik, sehingga batas waktu upaya membatalkannya dan penangan mencoba kembali. Setelah 30 detik, batas waktu total membatalkan permintaan dan kode Anda mendapatkan TimeoutRejectedException. Periksa apakah aplikasi Anda menangkapnya dan memberi tahu pengguna apa yang terjadi.

Tip

Untuk menguji skenario yang sama dengan pengaturan ketahanan Anda sendiri, ubah nilai dalam panggilan Anda AddStandardResilienceHandler(options => ...) dan jalankan konfigurasi Proksi Dev yang sama lagi.

Langkah selanjutnya

Pelajari selengkapnya tentang mensimulasikan pembatasan pada API apa pun.

Baca juga