Penanganan kesalahan sementara dengan percobaan ulang gRPC

Oleh James Newton-King

Percobaan ulang gRPC adalah fitur yang memungkinkan klien gRPC untuk secara otomatis mencoba kembali panggilan yang gagal. Artikel ini membahas cara mengonfigurasi kebijakan coba lagi untuk membuat aplikasi gRPC yang tangguh dan toleran terhadap kesalahan di .NET.

Percobaan ulang gRPC memerlukan Grpc.Net.Client versi 2.36.0 atau yang lebih baru.

Penanganan kesalahan sementara

Panggilan gRPC dapat terganggu oleh kesalahan sementara. Kesalahan sementara meliputi:

  • Hilangnya konektivitas jaringan sesaat.
  • Tidak tersedianya layanan sementara.
  • Waktu habis karena beban server.

Ketika panggilan gRPC terganggu, klien melempar RpcException dengan detail tentang kesalahan. Aplikasi klien harus menangkap pengecualian dan memilih cara menangani kesalahan.

var client = new Greeter.GreeterClient(channel);
try
{
    var response = await client.SayHelloAsync(
        new HelloRequest { Name = ".NET" });

    Console.WriteLine("From server: " + response.Message);
}
catch (RpcException ex)
{
    // Write logic to inspect the error and retry
    // if the error is from a transient fault.
}

Menduplikasi logika coba lagi di seluruh aplikasi bersifat verbose dan rawan kesalahan. Untungnya klien .NET gRPC memiliki dukungan bawaan untuk percobaan ulang otomatis.

Mengonfigurasi kebijakan coba lagi gRPC

Kebijakan coba lagi dikonfigurasi sekali saat saluran gRPC dibuat:

var defaultMethodConfig = new MethodConfig
{
    Names = { MethodName.Default },
    RetryPolicy = new RetryPolicy
    {
        MaxAttempts = 5,
        InitialBackoff = TimeSpan.FromSeconds(1),
        MaxBackoff = TimeSpan.FromSeconds(5),
        BackoffMultiplier = 1.5,
        RetryableStatusCodes = { StatusCode.Unavailable }
    }
};

var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
    ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});

Kode sebelumnya:

  • MethodConfigMembuat . Kebijakan coba lagi dapat dikonfigurasi per metode dan metode dicocokkan menggunakan Names properti . Metode ini dikonfigurasi dengan MethodName.Default, sehingga diterapkan ke semua metode gRPC yang dipanggil oleh saluran ini.
  • Mengonfigurasi kebijakan coba lagi. Kebijakan ini menginstruksikan klien untuk secara otomatis mencoba kembali panggilan gRPC yang gagal dengan kode Unavailablestatus .
  • Mengonfigurasi saluran yang dibuat untuk menggunakan kebijakan coba lagi dengan mengatur GrpcChannelOptions.ServiceConfig.

Klien gRPC yang dibuat dengan saluran akan secara otomatis mencoba kembali panggilan yang gagal:

var client = new Greeter.GreeterClient(channel);
var response = await client.SayHelloAsync(
    new HelloRequest { Name = ".NET" });

Console.WriteLine("From server: " + response.Message);

Ketika percobaan ulang valid

Panggilan dicoba kembali ketika:

  • Kode status yang gagal cocok dengan nilai di RetryableStatusCodes.
  • Jumlah upaya sebelumnya kurang dari MaxAttempts.
  • Panggilan belum dilakukan.
  • Tenggat waktu belum terlampaui.

Panggilan gRPC dilakukan dalam dua skenario:

  • Klien menerima header respons. Header respons dikirim oleh server saat ServerCallContext.WriteResponseHeadersAsync dipanggil, atau ketika pesan pertama ditulis ke aliran respons server.
  • Pesan keluar klien (atau pesan jika streaming) telah melebihi ukuran buffer maksimum klien. MaxRetryBufferSize dan MaxRetryBufferPerCallSize dikonfigurasi pada saluran.

Panggilan yang dilakukan tidak akan mencoba lagi, terlepas dari kode status atau jumlah upaya sebelumnya.

Panggilan streaming

Panggilan streaming dapat digunakan dengan percobaan ulang gRPC, tetapi ada pertimbangan penting ketika digunakan bersama-sama:

  • Streaming server, streaming dua arah: RPC Streaming yang mengembalikan beberapa pesan dari server tidak akan mencoba lagi setelah pesan pertama diterima. Aplikasi harus menambahkan logika tambahan untuk membuat ulang server dan panggilan streaming dua arah secara manual.
  • Streaming klien, streaming dua arah: RPC streaming yang mengirim beberapa pesan ke server tidak akan mencoba lagi jika pesan keluar telah melebihi ukuran buffer maksimum klien. Ukuran buffer maksimum dapat ditingkatkan dengan konfigurasi.

Untuk informasi selengkapnya, lihat Saat percobaan ulang valid.

Coba lagi penundaan backoff

Penundaan backoff antara upaya coba lagi dikonfigurasi dengan InitialBackoff, , MaxBackoffdan BackoffMultiplier. Informasi selengkapnya tentang setiap opsi tersedia di bagian opsi coba lagi gRPC.

Penundaan aktual antara upaya coba lagi diacak. Penundaan acak antara 0 dan backoff saat ini menentukan kapan upaya coba lagi berikutnya dilakukan. Pertimbangkan bahwa bahkan dengan backoff eksponensial yang dikonfigurasi, meningkatkan backoff saat ini antara upaya, penundaan aktual antara upaya tidak selalu lebih besar. Penundaan diacak untuk mencegah percobaan kembali dari beberapa panggilan dari pengklusteran bersama-sama dan berpotensi membebani server.

Mendeteksi percobaan ulang dengan metadata

Percobaan ulang gRPC dapat dideteksi dengan adanya grpc-previous-rpc-attempts metadata. Metadata grpc-previous-rpc-attempts :

  • Secara otomatis ditambahkan ke panggilan yang dicoba ulang dan dikirim ke server.
  • Nilai menunjukkan jumlah upaya coba lagi sebelumnya.
  • Nilai selalu bilangan bulat.

Pertimbangkan skenario coba lagi berikut:

  1. Klien melakukan panggilan gRPC ke server.
  2. Server gagal dan mengembalikan respons kode status yang dapat dicoba kembali.
  3. Klien mencoba kembali panggilan gRPC. Karena ada satu upaya sebelumnya, grpc-previous-rpc-attempts metadata memiliki nilai 1. Metadata dikirim ke server dengan coba lagi.
  4. Server berhasil dan mengembalikan OK.
  5. Klien melaporkan keberhasilan. grpc-previous-rpc-attempts berada dalam metadata respons dan memiliki nilai 1.

Metadata grpc-previous-rpc-attempts tidak ada pada panggilan gRPC awal, adalah 1 untuk coba lagi pertama, 2 untuk coba lagi kedua, dan sebagainya.

Opsi coba lagi gRPC

Tabel berikut ini menjelaskan opsi untuk mengonfigurasi kebijakan coba lagi gRPC:

Opsi Deskripsi
MaxAttempts Jumlah maksimum upaya panggilan, termasuk upaya asli. Nilai ini dibatasi dengan GrpcChannelOptions.MaxRetryAttempts yang defaultnya menjadi 5. Nilai diperlukan dan harus lebih besar dari 1.
InitialBackoff Penundaan backoff awal antara upaya coba lagi. Penundaan acak antara 0 dan backoff saat ini menentukan kapan upaya coba lagi berikutnya dilakukan. Setelah setiap upaya, backoff saat ini dikalikan dengan BackoffMultiplier. Nilai diperlukan dan harus lebih besar dari nol.
MaxBackoff Backoff maksimum menempatkan batas atas pada pertumbuhan backoff eksponensial. Nilai diperlukan dan harus lebih besar dari nol.
BackoffMultiplier Backoff akan dikalikan dengan nilai ini setelah setiap upaya coba lagi dan akan meningkat secara eksponensial ketika pengali lebih besar dari 1. Nilai diperlukan dan harus lebih besar dari nol.
RetryableStatusCodes Kumpulan kode status. Panggilan gRPC yang gagal dengan status yang cocok akan dicoba kembali secara otomatis. Untuk informasi selengkapnya tentang kode status, lihat Kode status dan penggunaannya di gRPC. Setidaknya diperlukan satu kode status yang dapat diulang.

Lindung nilai

Hedging adalah strategi percobaan kembali alternatif. Hedging memungkinkan pengiriman beberapa salinan dari satu panggilan gRPC secara agresif tanpa menunggu respons. Panggilan gRPC yang di-hedged dapat dijalankan beberapa kali di server dan hasil pertama yang berhasil digunakan. Penting bahwa hedging hanya diaktifkan untuk metode yang aman untuk dieksekusi beberapa kali tanpa efek buruk.

Hedging memiliki pro dan kontra jika dibandingkan dengan percobaan ulang:

  • Keuntungan untuk hedging adalah mungkin mengembalikan hasil yang berhasil lebih cepat. Ini memungkinkan beberapa panggilan gRPC secara bersamaan dan akan selesai ketika hasil pertama yang berhasil tersedia.
  • Kerugian untuk hedging adalah bisa sia-sia. Beberapa panggilan dapat dilakukan dan semuanya berhasil. Hanya hasil pertama yang digunakan dan sisanya dibuang.

Mengonfigurasi kebijakan hedging gRPC

Kebijakan hedging dikonfigurasi seperti kebijakan coba lagi. Perhatikan bahwa kebijakan hedging tidak dapat dikombinasikan dengan kebijakan coba lagi.

var defaultMethodConfig = new MethodConfig
{
    Names = { MethodName.Default },
    HedgingPolicy = new HedgingPolicy
    {
        MaxAttempts = 5,
        NonFatalStatusCodes = { StatusCode.Unavailable }
    }
};

var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
    ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
});

Opsi hedging gRPC

Tabel berikut menjelaskan opsi untuk mengonfigurasi kebijakan hedging gRPC:

Opsi Deskripsi
MaxAttempts Kebijakan hedging akan mengirimkan hingga jumlah panggilan ini. MaxAttempts mewakili jumlah total semua upaya, termasuk upaya asli. Nilai ini dibatasi dengan GrpcChannelOptions.MaxRetryAttempts yang defaultnya menjadi 5. Nilai diperlukan dan harus 2 atau lebih besar.
HedgingDelay Panggilan pertama segera dikirim, panggilan hedging berikutnya ditunda oleh nilai ini. Ketika penundaan diatur ke nol atau null, semua panggilan hedged segera dikirim. HedgingDelay bersifat opsional dan default ke nol. Nilai harus nol atau lebih besar.
NonFatalStatusCodes Kumpulan kode status yang menunjukkan panggilan hedge lainnya mungkin masih berhasil. Jika kode status non-fatal dikembalikan oleh server, panggilan hedged akan berlanjut. Jika tidak, permintaan yang terutang akan dibatalkan dan kesalahan dikembalikan ke aplikasi. Untuk informasi selengkapnya tentang kode status, lihat Kode status dan penggunaannya di gRPC.

Sumber Daya Tambahan: