Bagaimana cara menghindari "coba lagi badai" dalam layanan terdistribusi?

10

"Coba lagi badai" disebabkan ketika klien dikonfigurasi untuk mencoba kembali beberapa kali sebelum menyerah, kebijakan coba lagi diperlukan karena paket kehilangan akan terjadi dalam operasi normal dari suatu layanan.

Ambil contoh ini:

Arsitektur Sampel

Jika misalnya layanan secara keseluruhan diskalakan untuk mendukung 80.000 permintaan per detik dan berjalan pada sekitar 80% kapasitas, lonjakan lalu lintas yang menyebabkan layanan menerima 101.000 permintaan per detik akan menyebabkan 1.000 dari permintaan tersebut gagal.

Ketika kebijakan coba lagi dimulai, Anda berakhir dengan 1.000+ permintaan tambahan, tergantung di mana kegagalan terdeteksi yang akan mendorong layanan secara keseluruhan hingga 102.000 permintaan per detik - dari sana layanan Anda berubah menjadi spiral kematian yang menggandakan jumlahnya permintaan gagal setiap detik.

Selain penyediaan besar-besaran layanan di luar transaksi puncak yang diproyeksikan, yang akan menjadi tidak efisien. Strategi apa yang dapat Anda terapkan untuk menghindari "coba lagi badai"?

Richard Slater
sumber
Jika 100kQPS adalah 80% dari kapasitas, maka 101kQPS seharusnya tidak menghasilkan kegagalan 1k, itu harus menghasilkan nol kegagalan - bukankah itu titik dari overprovisioning?
Adrian
@Adrian hak Anda, itu adalah contoh buat menjelaskan titik - saya mencoba menjadi cukup reduktif untuk membuat poin saya jelas tanpa terlalu abstrak. Saya telah mengoreksi "ditingkatkan untuk mendukung 100.000" menjadi "ditingkatkan untuk mendukung 80.000".
Richard Slater

Jawaban:

7

Itu tergantung pada apa yang Anda coba hindari.

Jika Anda mencoba untuk menghindari interupsi layanan dari sesuatu yang merupakan layanan yang benar-benar kritis (saya berpikir dalam hal "orang akan mati jika panggilan API saya tidak dilayani dengan tepat"), Anda perlu hanya menganggarkan untuk inefisiensi besar yang datang dari jauh melebihi penyediaan sumber daya khusus. Dan ya mereka harus berdedikasi, tidak ada ini memungkinkan untuk hal-hal lonjakan lalu lintas, beberapa layanan lonjakan sehingga akan menyebabkan pemadaman.

Dalam skenario yang jauh lebih mungkin bahwa layanan Anda turun akan merepotkan Anda dapat mengatasi masalah baik dari sisi klien dan server. Meskipun perlu dicatat bahwa secara logis tidak mungkin untuk benar-benar menyelesaikan masalah banyak lalu lintas karena tanpa memproses lalu lintas (yang menghabiskan sumber daya) Anda tidak dapat mengetahui apakah itu coba lagi, apakah itu coba lagi untuk permintaan yang berhasil tetapi tidak ditangani dengan benar oleh klien, jika itu DDOS, dll. Tetapi Anda dapat mengurangi dampak.

Dalam kode klien, tulis logika coba lagi yang masuk akal yang memiliki batas atas dan mekanisme untuk gagal anggun. Dengan begitu Anda tidak menempel pengguna Anda dalam loop tak terbatas dari permintaan gagal dan Anda hanya memberi mereka kesalahan mengatakan kepada mereka untuk mencoba apa pun yang baru saja mereka lakukan dalam waktu singkat.

Untuk infrastruktur sisi server Anda , solusi paling sederhana adalah mencekik. Batas keras pada permintaan, terutama jika Anda dapat mencoba dan menyebarkannya secara logis berdasarkan kasus penggunaan khusus Anda (mis. Jika Anda memiliki layanan terpusat membuat beberapa keputusan sulit, apakah Anda ingin mulai memblokir permintaan yang jauh secara geografis yang mungkin mengakibatkan benang menggantung sisi server? Atau Anda ingin mendistribusikan pemadaman kecil yang tak terhindarkan Anda secara merata? dll) Ini pada dasarnya bermuara pada kenyataan bahwa mengembalikan 503 dengan sengaja dari gateway adalah jauh lebih murah daripada membiarkan permintaan melalui dan mengirim 504 bagaimanapun. Pada dasarnya memaksa klien untuk berperilaku berdasarkan apa yang saat ini dapat Anda berikan dan memberikan tanggapan yang benar sehingga klien dapat bereaksi dengan tepat.

hvindin
sumber
5

Salah satu cara untuk mencegah badai coba ini adalah dengan menggunakan mekanisme backoff.

Dari bagian Implement backoff on retry dari Google App Engine Designing for Scale :

Kode Anda dapat mencoba lagi pada kegagalan, apakah memanggil layanan seperti Cloud Datastore atau layanan eksternal menggunakan URL Fetch atau Socket API. Dalam kasus ini, Anda harus selalu menerapkan kebijakan backoff eksponensial acak untuk menghindari masalah kawanan petir . Anda juga harus membatasi jumlah percobaan ulang dan menangani kegagalan setelah batas coba ulang maksimum tercapai.

Sebagian besar GAE API sudah memiliki mekanisme / kebijakan backoff yang diaktifkan secara default.

Dan Cornilescu
sumber
Terima kasih, menerapkan mekanisme backoff adalah saran yang bagus, saya biasanya pergi untuk backoff eksponensial yang dapat dikonfigurasi menggunakan Blok Aplikasi Penanganan Kesalahan Transient . Namun, selama 5+ tahun pengalaman operasional mengoperasikan aplikasi skala besar di Azure, bahkan dengan backoff eksponensial di tempat "coba lagi badai" masih sering terjadi - saya tidak pernah bisa menemukan strategi yang bisa diterapkan untuk menghindarinya.
Richard Slater