Cara Handle Error pada Microservice

Salah Penanganan maka Kiamat Menanti

D. Husni Fahri Rizal
The Legend
5 min readDec 31, 2020

--

Error handling atau penanganan error memiliki pengertian sebagai cara untuk antisipasi, deteksi, dan resolusi kesalahan pemrograman. Aplikasi yang baik akan bisa mencegah kesalahan jika dimungkinkan, memulihkan dari error tanpa harus menghentikan aplikasi, atau jika terjadi error secara global dan menyeluruh program kita dapat secara elegan menghentikan aplikasi dan menulis error informasi ke dalam media penyimpanan.

Penanganan error handling pada monolith arsitektur lebih mudah dibandingkan pada sistem terdistribusi atau microservice arsitektur. Pada monolith, menangani error dapat dilakukan langsung ke inti permasalahan. Sedangkan, pada microservice kita tidak bisa hanya mengandalkan penanganan masalah yang umum dilakukan pada monolith arsitektur.

Ketika suatu sistem sudah terdistribusi seperti microservice maka akan muncul masalah-masalah yang ketika pada monolith tidak terjadi. Misalkan, konektivitas antar service, serialisasi dan deserialisasi, downstream service yang mati, bug, dan yang paling umum adalah latency yang terjadi semakin tinggi dan terjadi blocking.

Kunci keberhasilan menangani error pada microservice adalah penanganan error yang sederhana tidak ribet dan dilakukan secara terus-menerus. Kuncinya adalah memecah kompleksitas dan menyederhanakan ingatlah Deivede at Impera dan KISS principle. Kita dapat mengelompokkan error kedalam dua kelompok yaitu, jenis Transient Error dan Non Transient Error.

Transient Error

Transient error adalah error yang terjadi sementara dikarenakan keadaan dari sistem atau resource hardware yang bermasalah atau terkena limitasi. Adapun, contoh dari jenis error ini adalah koneksi problem, service yang mati, rute jaringan mungkin tidak tersedia selama beberapa detik atau milidetik, layanan web mungkin mengalami beban tinggi dan mengirimkan pesan tidak tersedia layanan 503 HTTP yang terputus-putus atau database yang Anda coba akses mungkin sedang dalam proses dipindahkan ke server yang berbeda dan karenanya tidak tersedia selama beberapa detik.

Jenis error ini adalah adalah evil error yang susah untuk di detect dan bisa terjadi kapan saja. Intinya error ini intermiten.

Non Transient Error

Non Transient Error adalah error yang terjadi terus-menerus selama error tersebut belum dibenarkan. Contoh error ini adalah bug dan masalah pada serialisasi dan deserialisasi.Penangan jenis error ini mudah karena jelas terlihat dan mudah untuk kita reproduce.Kita dapat menanggulangi jenis error ini seperti cara penanganan error pada monolith arsitektur.

Penanganan Transient Error

Untuk menghandle jenis error ini umumnya dilakukan back off policy dan retry mekanisme pada operasi yang sedang berlangsung. Proses back off strategy dapat dilakukan dengan car-cara berikut.

  • Retry Immediately, ketika terjadi masalah kita langsung melakukan pemanggilan ulang tanpa ada jeda waktu.
  • Retry pada interval waktu yang pasti, ketika terjadi error kita akan menunggu selama waktu yang sudah pasti dan ditentukan.
  • Retry dengan Exponential Back-Off, ketika terjadi error kita akan menunggu selama waktu yang bertambah secara eksponensial misalkan 2, 4, 8, 16 , 32 , … detik lalu dilakukan pemanggilan ulang proses.

Solusi terbaik retry adalah dengan penggunaan retry dengan back off exponential, bahkan mungkin harus menambahkan Jitter juga. Kenapa retry dengan back off itu penting karena jika terjadi error transient maka kemungkinan besar dalam ukuran waktu yang sama setiap service akan melakukan retry secara langsung dan bersamaan sehingga biasanya akan menambah buruk situasi. Terkadang kelebihan beban request mengarah ke Denial of Service (DoS).

Menggunakan back-off eksponensial memastikan bahwa setiap klien yang memanggil ke service yang sedang bermasalah memberikan ruang bernapas yang cukup bagi service untuk pulih.

Beberapa algoritma back-off eksponensial juga menambahkan delta yang dihitung secara acak ke waktu back-off. Hal ini memastikan bahwa jika banyak klien menggunakan algoritma back off policy yang sama, waktu mencoba lagi mereka memiliki probabilitas yang lebih rendah untuk terjadi tabrakan. Misalnya, alih-alih hanya menggunakan waktu mundur eksponensial mentah yang mencoba ulang pada 2, 4, 8, 16 detik dll, rumus menambahkan delta +/- 20% acak sehingga waktu retry terjadi pada 1,7, 4,2, 8,5 , 15,4 detik. Ini lah yang di maksud menambahkan jitter pada proses back off.

Back off policy eksponensial tanpa Jitter
Bcak off policy eksponensial dengan Jitter

Beberapa framework yang dapat digunakan untuk retry dan back off ini diantaranya Spring Retry dan Resilience4j untuk Java programing atau https://github.com/avast/retry-go atau https://github.com/gojek/heimdall untuk bahasa pemograman go.

Kapan Harus Melakukan Retry

Tidak semua error kita harus melakukan pemanggilan ulang kembali. Seusai dengn definisi di atas kita hanya akan melalukan retry untuk jenis-jenis error transient. Apabila third party service atau layanan database yang kita panggil sudah memiliki jenis error TransientErrorException sangat bagus dan mudah kita mendeteksinya. Akan tetapi, kebanyakan sistem belum mempunyai error secara spesifik. Dengan demikian, kita harus cerdas dalam menangai jenis error ini.

Menurut definisi spesifikasi HTTP 2 , GET, HEAD, PUT, dan DELETE adalah operasi idempoten. Jadi, Anda boleh mencoba kembali permintaan tersebut kecuali disarankan oleh pemilik service yang kita panggil. Di sisi lain, POST & PATCH tidak idempoten dan jika idempotensi tidak diterapkan, tidak aman untuk mencoba lagi karena dapat menyebabkan efek samping seperti menagih pelanggan beberapa kali.

Dead Letter Events

Cara penanggulangan error handling karena error transient di atas, masih menungkinkan data yang masuk ketika terjadi error transient akan hilang karena sudah beberapa kali retry sistem masih bermasalah.

Salah satu solusi adalah kita menyediakan satu service yang menghandle penyimpanan data ketika retry masih tidak mampu menangani permasalahan. Ketika problem terjadi kita menarik keluar dari pipeline dan melemparkan ke service ini. Service ini akan menyimpan data yang bermasalah ini dan akan mengeksekusi kembali setelah sistem benar-benar pulih. Dengan demikian, kita tidak akan kehilangan data ketika permasalah terjadi.

Cara implementasi dead letter event biasanya menggunakan message broker agar proses terjadi asynchronous dan non blocking. Misalkan kita menggunakan Kafka dikombinasiakan dengan NoSQL media penyimpanannya dan lebih bagus terdapat scheduler.

Contoh penanganan dengan dead letter event

Selain Retry dan Dead Letter Event terdapat mekanisme lain untuk menghandle error transient ini . Salah satunya adalah Circuit Breaker dan Ratelimiter yang akan kita coba bahas pada pada Side Car Service, Client Side Load Balancing dan Api Gateway.

Sebagai penutup, penanganan error pada microservice atau sistem terdistribusi umumnya memerlukan penanganan yang tidak mudah dan perlu dirancang dengan baik. Setelah dirancang dengan baik jangan lupa kita harus melakukan test atau simulasi terhadap transient error ini terjadi di production. Akantetapi, untuk dapat melakukan simulasi error transient tidak mudah apalagi di production, Chaos Monkey sebagai bagian dari Chaos Engineering adalah salah satu cara melakukan simulasi error transient ini. Mungkin suatu saat kita coba membahas bagaimana Netflix dan Chaos Mongkey nya.

References

  1. https://netflix.github.io/chaosmonkey/
  2. https://en.wikipedia.org/wiki/Chaos_engineering
  3. https://www.gremlin.com/chaos-monkey/
  4. https://github.com/Netflix/chaosmonkey
  5. https://github.com/avast/retry-go
  6. https://github.com/gojek/heimdall
  7. https://docs.spring.io/spring-batch/docs/current/reference/html/retry.html
  8. https://resilience4j.readme.io/docs/getting-started

Sponsor

Membutuhkan kaos dengan tema pemrograman :

Kafka T-shirt

Elastic T-shirt

Dapat menghubungi The Legend.

--

--

D. Husni Fahri Rizal
The Legend

Engineering Leader | Start-Up Advisor | Agile Coach | Microservices Expert | Professional Trainer | Investor Pemula