Circuit Breaker Pattern
Implementasi dengan C#
Note : posting kali ini saya berasumsi teman-teman sudah paham dasar C#dan OOP (object oriented programming).
Okayyyy! kali ini saya ingin cerita membuat kode untuk download file dari sebuah url. Coder pemula biasanya menulis kode langsung saja tanpa pikir panjang (kadang-kadang yang senior juga begitu hehe). Misal kita akan men-download logo neraka ngoding dari url :
https://cdn-images-1.medium.com/max/240/1*Z_ZWH-3GFo_Y9kVHqLSA7g@2x.png
Dengan kode 1
Penjelasan kode 1 :
- Baris 12 akan menulis ke terminal “Download neraka ngoding”.
- Baris 14 adalah url gambar logo neraka ngoding.
- Baris 15 logo neraka ngoding di-download sebagai file nerakangoding.png.
- Baris 17 static method Download dengan parameter uri (url) dan fileName akan dieksekusi. Karena method Download asychronous maka program tidak akan blocking, tetapi karena program diatas adalah program console setelah eksekusi method Dowload program akan langsung selesai karena itu kita menunggu proses dowload selesai dengan .wait(). Static method adalah jenis method yang bisa diakses dari suatu class tanpa instantiasi object dari class tersebut. Instantiasi adalah proses penciptaan object dari class. apa beda object ama class? ayoooo!! jadi ceramah oop nih dafuq dah!.
- baris 20 sampai 34 implementasi download dengan cara asynchronous saya bahas disini. Pake async la yah biasakan untuk proses-proses yang memakan waktu biar tidak blocking eksekusi kode nya. Inti kode method Download :
- Buat http request dengan
var request = new HttpRequestMessage(HttpMethod.Get, uri)
2. Execute request nomor 1 (GET adalah http method untuk request resource di server) hasilnya di-convert menjadi object Stream
await httpClient.SendAsync(request)).Content.ReadAsStreamAsync()
3. Stream dirubah menjadi FileStream.
stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
await contentStream.CopyToAsync(stream);
}
Hasil running program di komputer mac saya
OK beres-beres bubar-bubar file sudah bisa di download pakai async method lagi, tidak secepat itu kawan bagaimana kalau server yang menyimpan file yang akan di-download down sementara program diatas akan gagal men-dowload file nya kemudian dijalankan lagi programnya berhasil download file-nya. Lebih jauh lagi kalau kode download itu dipakai di aplikasi kita sebagian user akan merasakan gagal download, user yang lain akan merasakan berhasil dowload. Untuk mengatasi problem diatas ada baiknya kode download file nya kalau gagal ada mekanisme ‘retry’ biar kode download nya reliable jadi kalau sekali download gagal kode akan mencoba lagi untuk download misal kita batasi percobaan download sebanyak tiga kali. Untuk implementasikan mekanisme ‘retry’ bisa kita coding sendiri namun ada cara lebih cepat pake package Polly.
Penjelasan kode 2
- Baris 15 akan memanggil method asynchronous RetryDownload().
- Baris 17 adalah perintah untuk membaca input dari terminal kalau di tekan keyboard apa saja akan menutup program.
- Baris 20 sampai 40 adalah definisi method RetryDownload yang isi nya akan mengeksekusi Method Download dengan cara Retry Pattern yang artinya kalau gagal eksekusi method Download akan dicoba lagi sebanyak tiga kali dengan jeda waktu antara percobaan eksekusi Dowload selama dua detik. Setiap gagal download akan menuliskan seperti “Request failed with NotFound. Waiting 00:00:02 before next retry. Retry attempt 1”
var response = await Policy
.HandleResult<HttpResponseMessage>(message =>!message.IsSuccessStatusCode)
.WaitAndRetryAsync(3, i => TimeSpan.FromSeconds(2), (result, timeSpan, retryCount, context) =>
{
Console.WriteLine($”Request failed with {result.Result.StatusCode}. Waiting {timeSpan} before next retry. Retry attempt {retryCount}”);
})
.ExecuteAsync(() => Download(uri,filename));
Url sengaja saya rubah menjadi
https://cdn-images-1.medium.com/max/240/1*Z_ZWH-3GFo_Y9kVHqLSA7g@2xdsa.png
supaya download-nya gagal dan mencoba tiga kali.
- Baris 35–36 kalau download berhasil akan menuliskan “Response was successful.”
- Baris 38 Jika setelah percobaan tiga kali tetap gagal download maka akan menuliskan “Response failed. Status code NotFound”.
- Baris 42 -60 sama definisi method Dowload sama seperti kode 1 tetapi return value nya menjadi Task<HttpResponseMessage>.
Output program seperti ini
Kode 2 diatas sudah cukup bagus dibandingkan dengan kode 1 karena reliable jadi kalau misalkan server-nya down sementara maka program akan mencoba lagi untuk download. Jumlah percobaan download didefinisikan di-method RetryDownload.
Sekarang bayangkan situasi seperti ini, kita ingin percobaan download terus menerus tidak hanya tiga kali dan katakanlah kode download tersebut terdapat didalam sebuah website dan diakses oleh banyak user yang akan menambah traffic ke server dan berpotensi server menjadi down, ada yang ngerasa janggal dengan situasi ini?
Serangan DoS (bahasa Inggris: denial-of-service attacks’) adalah jenis serangan terhadap sebuah komputer atau server di dalam jaringan internet dengan cara menghabiskan sumber (resource) yang dimiliki oleh komputer tersebut sampai komputer tersebut tidak dapat menjalankan fungsinya dengan benar.
Kode 2 diatas salah method RetryDownload().Wait(); dipanggil lebih dari satu kali. Kita lihat kode 3 berikut
Output
Penjelasan kode 3
- Baris 17 deklarasi private member AsyncCircuitBreakerPolicy<HttpResponseMessage> yaitu Circuit Breaker Policy object dengan nilai balik HttpResponseMessage. Circuit Breaker Pattern akan dijelaskan pada penjelesan kode 3 ini dibawah.
- Baris 18 deklarasi private member AsyncRetryPolicy<HttpResponseMessage> seperti retry pattern dikode 2.
- Baris 19 deklarasi private member AsyncFallbackPolicy<HttpResponseMessage> yaitu fallback policy object dengan nilai balik HttpResponseMessage akan dijelaskan dibawah juga.
- Baris 20 deklarasi private static member AsyncPolicyWrap<HttpResponseMessage> policyWrap yaitu object policy Gabungan.
- Baris 25–33 adalah proses instantiasi object circuitBreakerPolicy dengan karakteristik sebagai berikut
- Baris 26 Circuit breaker akan meng-handle kalau terjadi HttpResponseMessage Not Found Statusnya.
- Baris 29 kalau terjadi HttpResponseMessage Not Found sebanyak tiga kali maka status circuit breaker status menjadi open artinya kalo ada Request download ke-4 tidak dilayani proses download, disini letak bagus nya circuit breaker pattern kalau program sudah tahu download nya gagal ngapain request ke-4,5,6 dst dilayani, hal ini akan menjadi beban server lebih ringan.
- Baris 30 kalau terjadi status open di Circuit Breaker setiap request download tidak akan dilayani selama 20 detik.
- Baris 31–32 akan menuliskan keterminal “Breaking the circuit for 20 seconds due to” ketika Circuit Breaker statusnya open.
- Baris 33 akan menuliskan ke-terminal “Call ok — closing the circuit again.” ketika Circuit Breaker statusnya closed atau kalau server sudah up lagi.
- Baris 34 akan menuliskan ke-terminal “Circuit is half-open. The next call is a trial” ketika status Circuit Breaker statusnya half-open yaitu ketika 20 detik sudah habis waktunya request berikutnya akan dicoba untuk menentukan apakah server sudah up atau belum, kalau berhasil status Circuit Breaker akan menjadi closed nomor 5 kalau gagal status Circuit Breaker akan menjadi open lagi nomor 4.
- Baris 37–44 adalah proses instantiasi object retryPolicy dengan karakteristik sebagai berikut :
- Baris 38 Retry akan diulang jika status HttpResponseMessage Not Found.
- Baris 39 Retry akan dilakukan terus menerus.
- Baris 40 Jika terjadi Retry akan ditunggu selama 2 detik untuk retry berikutnya.
- Baris 41–44 akan menuliskan ‘Retry’ ke-terminal jika terjadi Retry.
- Baris 47–54 adalah proses instantiasi object fallbackForCircuitBreaker. Fallback Policy akan dieksekusi kalau terjadi Circuit Breaker Open.
- Baris 56 menggabungkan retryPolicy dan circuitBreakerPolicy menjadi object resilentStrategy.
- Baris 57 menggabungkan resilentStrategy dengan fallbackForCircuitBreaker disimpan di object policyWrap.
- Baris 60 sama seperti kode 2 eksekusi method RetryDownload1(), dimana url logo neraka ngoding dibuat salah pada retry ke tiga circuit breaker statusnya akan menjadi open.
- Baris 62 thread program diberhentikan selama 20 detik tujuannya supaya circuit breaker baris 30 sudah selesai statusnya open nya jika terjadi open oleh RetryDownload1(), memang bakal terjadi open karena url dari logo neraka ngoding dibuat salah.
- Baris 64 sama seperti kode 2 eksekusi method RetryDownload2(), dimana url logo neraka ngoding dibuat benar.
Penjelasan Output
1. Retry2. Retry3. Breaking the circuit for 20 seconds due to4. Retry5. Operation attempted on broken circuit => Policy Wrap: AsyncPolicyWrap`1–0d9de0dc, Policy: AsyncFallbackPolicy`1-d386d22a, Endpoint:6. Response failed. Status code NotFound7. Circuit is half-open. The next call is a trial.8. Call ok — closing the circuit again.9. Response was successful.
- Baris 1 program akan Retry 1x karena method RetryDownload1 url logo neraka ngoding dibuat salah.
- Baris 2 program akan Retry 2x karena method RetryDownload1 url logo neraka ngoding dibuat salah.
- Baris 3 program akan Retry 3x karena circuit breaker membatasi 3x Retry maka akan terjadi status Open pada circuit breaker dengan dituliskannya “Breaking the circuit for 20 seconds due to” , maka jika ada retry lagi fallback policy akan dieksekusi.
- Baris 4 dan Baris 5 karena retry policy terus menerus tidak dibatasi Kode 3 baris 39 maka program akan retry lagi, tetapi kali ini karena status circuit breaker lagi open maka fallback policy akan dieksekusi maka akan menulis “Operation attempted on broken circuit => Policy Wrap: AsyncPolicyWrap`1–0d9de0dc, Policy: AsyncFallbackPolicy`1-d386d22a, Endpoint:” bagus kan? tuh udah tau gagal ngapain diteruskan ke server jadi beban server lebih ringan.
- Baris 6 “Response failed. Status code NotFound” method RetryDownload1() akan berhenti walaupun retry nya terus menerus.
- Baris 7 method RetryDownload2() dieksekusi. Karena ada kode Thread.Sleep(20000); untuk menunggu circuit breaker waktu status open nya habis dan status nya menjadi half open sehingga circuit breaker akan menuliskan ke-terminal “Circuit is half-open. The next call is a trial.” ketika retry pertama method RetryDownload2()
- Baris 8 karena eksekusi method RetryDownload2() url logo neraka ngoding dibuat benar maka circuit breaker statusnya akan menjadi closed setelah retry pertama dan berhasil. Circuit Breaker akan menuliskan ke-terminal “Call ok — closing the circuit again”.
- Baris 9 eksekusi method RetryDownload2 berhasil dan akan menuliskan “Response was successful”.
Kesimpulan Circuit Breaker Patern :
- Status nya menjadi Open ketika Cicuit Breaker sudah lewati batas proses akses (download kode 3) gagal.
- Ketika statusnya mulai open Circuit breaker akan menghalangi proses akses selama waktu tertentu (20 detik kode 3).
- Setelah waktu open habis ketika ada proses akses lagi maka statusnya akan menjadi Half-open.
- Jika ketika statusnya Half-open dan prosesnya berhasil maka status nya akan menjadi Closed lagi yang artinya bisa dilewati proses akses yang lain.
Cara kerjanya mirip dengan sekring dirumah-rumah atau fuse atau circuit breaker. Circuit Breaker Pattern cocok dipakai pada design API microservices.
Ok segitu dulu semoga pusing emang koding seperti ini udah mulai neraka, tetapi kalo teman-teman sudah ngoding seperti ini menggunakan pattern selamat teman-teman sudah satu level diatas coder yang asal jadi. Sampai jumpa di posting berikutnya.