Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Petunjuk / Saran
Konten ini adalah kutipan dari eBook, Arsitektur Layanan Mikro .NET untuk Aplikasi .NET Kontainer, tersedia di .NET Docs atau sebagai PDF gratis yang dapat diunduh yang dapat dibaca secara offline.
Seperti disebutkan sebelumnya, Anda harus menangani kesalahan yang mungkin membutuhkan waktu variabel untuk pulih, seperti yang mungkin terjadi ketika Anda mencoba menyambungkan ke layanan atau sumber daya jarak jauh. Menangani jenis kesalahan ini dapat meningkatkan stabilitas dan ketahanan aplikasi.
Dalam lingkungan terdistribusi, panggilan ke sumber daya dan layanan jarak jauh dapat gagal karena kesalahan sementara, seperti koneksi jaringan yang lambat dan batas waktu, atau jika sumber daya merespons dengan lambat atau sementara tidak tersedia. Gangguan ini biasanya memperbaiki diri sendiri setelah waktu yang singkat, dan aplikasi cloud yang kuat harus siap untuk menanganinya dengan menggunakan strategi seperti "pola percobaan ulang".
Namun, mungkin juga ada situasi di mana kesalahan disebabkan oleh peristiwa yang tidak terduga yang mungkin memakan waktu lebih lama untuk diperbaiki. Keparahan kesalahan ini dapat berkisar mulai dari hilangnya sebagian konektivitas hingga kegagalan total layanan. Dalam situasi ini, mungkin tidak ada gunanya bagi aplikasi untuk terus mencoba kembali operasi yang tidak mungkin berhasil.
Sebaliknya, aplikasi harus dikodekan untuk menerima bahwa operasi telah gagal dan menangani kegagalan yang sesuai.
Menggunakan percobaan ulang Http sembarangan dapat mengakibatkan serangan Denial of Service (DoS) dalam perangkat lunak Anda sendiri. Karena layanan mikro gagal atau berkinerja lambat, beberapa klien mungkin berulang kali mencoba kembali permintaan yang gagal. Itu menciptakan risiko berbahaya peningkatan eksponensial lalu lintas yang ditargetkan pada layanan yang mengalami kegagalan.
Oleh karena itu, Anda memerlukan semacam hambatan pertahanan sehingga permintaan yang berlebihan berhenti ketika tidak layak untuk terus mencoba. Hambatan pertahanan itu tepatnya adalah pemutus sirkuit.
Pola Circuit Breaker memiliki tujuan yang berbeda dari "Pola coba lagi". "Pola coba lagi" memungkinkan aplikasi untuk mencoba kembali operasi dengan harapan bahwa operasi pada akhirnya akan berhasil. Pola Circuit Breaker mencegah aplikasi melakukan operasi yang kemungkinan gagal. Aplikasi dapat menggabungkan kedua pola ini. Namun, logika coba lagi harus sensitif terhadap pengecualian apa pun yang dikembalikan oleh pemutus sirkuit, dan harus meninggalkan upaya coba lagi jika pemutus sirkuit menunjukkan bahwa kesalahan tidak sementara.
Menerapkan pola 'Circuit Breaker' menggunakan IHttpClientFactory dan Polly
Seperti saat menerapkan percobaan ulang, pendekatan yang direkomendasikan untuk pemutus sirkuit adalah memanfaatkan pustaka .NET yang terbukti seperti Polly dan integrasi aslinya dengan IHttpClientFactory.
Menambahkan kebijakan pemutus sirkuit ke dalam alur middleware keluar Anda IHttpClientFactory semudah menambahkan satu kode inkremental ke apa yang sudah Anda miliki saat menggunakan IHttpClientFactory.
Satu-satunya penambahan di sini untuk kode yang digunakan untuk percobaan ulang panggilan HTTP adalah kode tempat Anda menambahkan kebijakan Circuit Breaker ke daftar kebijakan yang akan digunakan, seperti yang ditunjukkan dalam kode inkremental berikut.
// Program.cs
var retryPolicy = GetRetryPolicy();
var circuitBreakerPolicy = GetCircuitBreakerPolicy();
builder.Services.AddHttpClient<IBasketService, BasketService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) // Sample: default lifetime is 2 minutes
.AddHttpMessageHandler<HttpClientAuthorizationDelegatingHandler>()
.AddPolicyHandler(retryPolicy)
.AddPolicyHandler(circuitBreakerPolicy);
Metode AddPolicyHandler() inilah yang menambahkan kebijakan ke HttpClient objek yang akan Anda gunakan. Dalam hal ini, ini menambahkan kebijakan Polly untuk pemutus sirkuit.
Untuk memiliki pendekatan yang lebih modular, Kebijakan Pemutus Sirkuit didefinisikan dalam metode terpisah yang disebut GetCircuitBreakerPolicy(), seperti yang ditunjukkan dalam kode berikut:
// also in Program.cs
static IAsyncPolicy<HttpResponseMessage> GetCircuitBreakerPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30));
}
Dalam contoh kode di atas, kebijakan pemutus sirkuit dikonfigurasi sehingga rusak atau membuka sirkuit ketika ada lima kesalahan berturut-turut saat mencoba kembali permintaan Http. Ketika itu terjadi, sirkuit akan pecah selama 30 detik: dalam periode itu, panggilan akan segera gagal oleh pemutus sirkuit daripada benar-benar ditempatkan. Kebijakan ini secara otomatis menginterpretasikan pengecualian yang relevan dan kode status HTTP sebagai kesalahan.
Pemutus arus juga harus digunakan untuk mengalihkan permintaan ke infrastruktur fallback jika Anda mengalami masalah dalam sumber daya tertentu yang disebarkan di lingkungan yang berbeda dari aplikasi atau layanan klien yang melakukan panggilan HTTP. Dengan begitu, jika ada pemadaman di pusat data yang hanya memengaruhi layanan mikro backend Anda tetapi bukan aplikasi klien Anda, aplikasi klien dapat mengalihkan ke layanan fallback. Polly merencanakan kebijakan baru untuk mengotomatiskan skenario kebijakan failover ini.
Semua fitur tersebut adalah untuk kasus di mana Anda mengelola failover dari dalam kode .NET, dibandingkan dengan mengelolanya secara otomatis untuk Anda oleh Azure, dengan transparansi lokasi.
Dari sudut pandang penggunaan, saat menggunakan HttpClient, tidak perlu menambahkan sesuatu yang baru di sini karena kodenya sama dengan saat menggunakan HttpClient dengan IHttpClientFactory, seperti yang ditunjukkan di bagian sebelumnya.
Menguji ulang HTTP dan pemutus sirkuit di eShopOnContainers
Setiap kali Anda memulai solusi eShopOnContainers di host Docker, itu perlu memulai beberapa kontainer. Beberapa kontainer lebih lambat untuk memulai dan menginisialisasi, seperti kontainer SQL Server. Ini terutama berlaku saat pertama kali Anda menyebarkan aplikasi eShopOnContainers ke Docker karena perlu menyiapkan gambar dan database. Fakta bahwa beberapa kontainer mulai lebih lambat daripada yang lain dapat menyebabkan sisa layanan awalnya melemparkan pengecualian HTTP, bahkan jika Anda mengatur dependensi antara kontainer di tingkat docker-compose, seperti yang dijelaskan di bagian sebelumnya. Dependensi docker-compose antara kontainer hanya berada di tingkat proses. Proses utama kontainer mungkin sudah dimulai, tetapi SQL Server mungkin belum siap untuk menjalankan kueri. Hasilnya bisa menjadi rentetan kesalahan, dan aplikasi bisa mendapatkan pengecualian saat mencoba memproses kontainer tertentu.
Anda mungkin juga melihat jenis kesalahan ini saat startup saat aplikasi disebarkan ke cloud. Dalam hal ini, orkestrator mungkin memindahkan kontainer dari satu simpul atau VM ke simpul lain (yaitu, memulai instans baru) saat menyeimbangkan jumlah kontainer di seluruh simpul kluster.
Cara 'eShopOnContainers' memecahkan masalah tersebut saat memulai semua kontainer adalah dengan menggunakan pola Coba lagi yang diilustrasikan sebelumnya.
Menguji pemutus sirkuit di eShopOnContainers
Ada beberapa cara untuk merusak/membuka sirkuit dan mengujinya dengan eShopOnContainers.
Salah satu opsinya adalah menurunkan jumlah percobaan ulang yang diizinkan menjadi 1 dalam kebijakan pemutus sirkuit dan menyebarkan ulang seluruh solusi ke Docker. Dengan satu kali percobaan ulang, ada kemungkinan besar permintaan HTTP akan gagal saat proses deployment, sehingga pemutus sirkuit akan aktif dan Anda mendapatkan pesan kesalahan.
Opsi lain adalah menggunakan middleware kustom yang diimplementasikan dalam mikroservis Keranjang. Ketika middleware ini diaktifkan, middleware ini menangkap semua permintaan HTTP dan mengembalikan kode status 500. Anda dapat mengaktifkan middleware dengan membuat permintaan GET ke URI yang gagal, seperti berikut ini:
GET http://localhost:5103/failing
Permintaan ini mengembalikan status middleware saat ini. Jika middleware diaktifkan, permintaan mengembalikan kode status 500. Jika middleware dinonaktifkan, tidak ada respons.GET http://localhost:5103/failing?enable
Permintaan ini memungkinkan berfungsinya middleware.GET http://localhost:5103/failing?disable
Permintaan ini menonaktifkan middleware.
Misalnya, setelah aplikasi berjalan, Anda dapat mengaktifkan middleware dengan membuat permintaan menggunakan URI berikut di browser apa pun. Perhatikan bahwa layanan mikro pemesanan menggunakan port 5103.
http://localhost:5103/failing?enable
Anda kemudian dapat memeriksa status menggunakan URI http://localhost:5103/failing, seperti yang ditunjukkan pada Gambar 8-5.
Gambar 8-5. Memeriksa status middleware ASP.NET yang disebut "Failing" – Dalam hal ini, dinonaktifkan.
Pada titik ini, layanan mikro Basket merespons dengan kode status 500 setiap kali Anda memanggilnya.
Setelah middleware berjalan, Anda dapat mencoba membuat pesanan dari aplikasi web MVC. Karena permintaan gagal, sirkuit akan terbuka.
Dalam contoh berikut, Anda dapat melihat bahwa aplikasi web MVC memiliki blok catch dalam logika pemrosesan pesanan. Jika kode menangkap pengecualian sirkuit terbuka, kode memberikan pesan yang ramah kepada pengguna yang memberi tahu mereka untuk menunggu.
public class CartController : Controller
{
//…
public async Task<IActionResult> Index()
{
try
{
var user = _appUserParser.Parse(HttpContext.User);
//Http requests using the Typed Client (Service Agent)
var vm = await _basketSvc.GetBasket(user);
return View(vm);
}
catch (BrokenCircuitException)
{
// Catches error when Basket.api is in circuit-opened mode
HandleBrokenCircuitException();
}
return View();
}
private void HandleBrokenCircuitException()
{
TempData["BasketInoperativeMsg"] = "Basket Service is inoperative, please try later on. (Business message due to Circuit-Breaker)";
}
}
Berikut ringkasannya. Kebijakan coba ulang mencoba beberapa kali untuk mengirimkan permintaan HTTP dan mengalami kesalahan HTTP. Ketika jumlah percobaan ulang mencapai jumlah maksimum yang ditetapkan untuk kebijakan Circuit Breaker (dalam hal ini, 5), aplikasi melempar BrokenCircuitException. Hasilnya adalah pesan ramah, seperti yang ditunjukkan pada Gambar 8-6.
Gambar 8-6. Pemutus sirkuit mengirimkan kesalahan ke antar muka pengguna
Anda dapat menerapkan logika yang berbeda kapan harus membuka/merusak sirkuit. Atau Anda dapat mencoba permintaan HTTP terhadap layanan mikro back-end yang berbeda jika ada pusat data cadangan atau sistem back-end yang redundant.
Akhirnya, kemungkinan lain untuk CircuitBreakerPolicy adalah menggunakan Isolate (yang memaksa membuka dan menahan terbuka sirkuit) dan Reset (yang menutupnya lagi). Ini dapat digunakan untuk membangun titik akhir HTTP utilitas yang memanggil Isolasi dan Reset langsung pada kebijakan. Titik akhir HTTP seperti itu juga dapat digunakan, dengan keamanan yang sesuai, dalam lingkungan produksi untuk mengisolasi sistem di hilir secara sementara, misalnya, ketika Anda ingin melakukan peningkatan. Atau itu bisa memutus sirkuit secara manual untuk melindungi sistem di bawahnya yang Anda duga mengalami kerusakan.
Sumber daya tambahan
-
Pola Pemutus Sirkuit
https://learn.microsoft.com/azure/architecture/patterns/circuit-breaker