Mendesain Event-Driven Architecture — Part 4
Event sebagai Dasar dari Kolaborasi pada Sistem
Hampir semua arsitektur software yang dibuat sekarang ini yang berbasis service, microservice, ataupun SOA umumnya dibangun dengan protokol request-response yang sinkron. Pendekatan ini sangat umum dan alami. Kita membuat request dan menunggu tanggapan atau balikannya.
Akan tetapi, berbeda cerita ketika kita masuk ke sistem yang sudah memiliki jumlah user yang sangat banyak atau jumlah service independen (microservice) yang sudah sangat banyak juga, segalanya mulai berubah.
Ketika suatu software dengan request response yang sinkron dan jumlah user yang menggunakan sudah sangat banyak akan timbul permasalahan penurunan response time, latency, dan blocking proses. Semua hal ini akan mengarah ke tingkat performance, reliability, dan availability yang mulai terganggu dan menurun secara drastis.
Untuk sistem yang sudah mengimplementasikan microservice mungkin penanganan mengenai hal-hal di atas akan lebih baik. Akan tetapi jumlah service yang terus bertambah mengakibatkan komunikasi antar service yang masih menggunakan pendekatan request response yang sinkron akan berbahaya (latency dan blocking proses), dapat memicu kegagalan sistem yang meluas. Pembahasan mengenai contoh dari masalah ini dapat dibaca di artikel Handling Error pada Microservice dan Circuit Breaker pada Microservice.
Terdapat beberapa solusi untuk menangani permasalahan-permasalahan di atas. Cara pertama yakni kita harus memastikan semua SLA service-service yang ada pada sistem kita harus lebih tinggi dari SLA sistem secara keseluruhan. Untuk melakukan kalkulasi mengenai hal ini dapat dibaca pada The Calculus of Availability. Solusi kedua adalah dengan memecah singkron proses menjadi beberapa proses asingkron dengan perantara message broker.
Di dunia e-commerce kita sudah terbiasa dengan proses singkron seperti getImage() atau processOreder(). Ketika kita melakukan request maka kita mengharapkan secara langsung dapat responsenya. Akan tetapi, ketika user melakukan pembelian dengan menekan tombol Buy pada dasarnya proses yang dilakukan sangat kompleks, panjang, dan aksi yang tidak singkron.
Kejadian sebenarnya di belakang layar adalah pembeli melakukan pembelian dan secara fisik barang dihantarkan sampai ke depan pintu pembeli. Jadi, seberanya proses pembelian ini jauh dari konteks klik tombol tadi. Dengan demikian, membagi proses tadi kedalam beberapa proses asingkron, mengelompokkannya dalam kelompok-kelompok tertentu adalah suatu tindakan yang dapat kita lakukan demi proses dan performance yang lebih baik.
Command, Event, dan Query
Sebelum membahas lebih jauh, alangkah baiknya kita bahas terlebih dahulu bagaimana cara program atau software berinteraksi melalui jaringan komputer. Terdapat tiga cara yakni, command, event, dan query.
Command
Command adalah tindakan atau aksi yang dilakukan oleh user untuk beberapa operasi sehingga dari operasi ini melakukan perubahan terhadap sistem (database). Proses akan dilakukan secara singkron dan umumnya menunjukan proses penyelesaian. Untuk beberapa kondisi tertentu dari prosesnya akan mengembalikan atau menyertakan hasil.
Contoh dari command misalkan payment proses yang akan mengembalikan informasi payment tersebut sukses atau gagal di eksekusi. Kadang juga proses command selain informasi membawa juga data yang kita ubah atau simpan tersebut.
Kondisi yang tepat untuk menggunakan command adalah ketika kita membutuhkan proses yang betul-betul harus singkron dan kita membutuhkan informasi proses tadi diketahui statusnya berhasil atau tidak.
Event
Event , kejadian, atau peristiwa pada dasarnya merupakan fakta dan pemberitahuan. Event ini mewakili atau menggambarkan yang terjadi pada dunia nyata tetapi tidak termasuk harapan kejadian di masa depannya. Event ini berjalan hanya dalam satu arah dan tidak mengharapkan tanggapan. Kadang kita menyebutnya sebagi fire and forget proses
Contoh event adalah peristiwa order terbentuk atau peristiwa customer detil terupdate. Jadi, bukan proses ordernya dibuat atau diminta tetapi kejadian sesaat setelah order terbentuk.
Kondisi yang tepat untuk penggunaannya adalah ketika kondisi loose coupling sangat penting. Kondisi lainnya adalah ketika aliran peristiwa(event stream) digunakan atau diconsume oleh lebih dari satu service dan data perlu direplikasi dari satu aplikasi ke aplikasi lainnya.
Event ini cocok juga ketika suatu request akan diproses secara bersamaan untuk meningkatkan performance baik dengan cara paralel (satu proses besar atau banyak dalam satu request) atau concurrency (banyak request dalam satu waktu).
Query
Query ada proses permintaan untuk mencari sesuatu. Tidak seperti event atau command, query terbebas dari berbagai side efect. Permintaan akan meninggalkan keadaan sistem tidak berubah.
Contoh query adalah permintaan data detil untuk id tertentu yang akan memberikan informasi balik data yang diminta. Waktu yang tepat untuk menggunakan query adalah untuk proses pencarian yang ringan ataupun pencarian yang berat dalam batas-batas tertentu.
Kembali kepada event, event memiliki dua hal yang paling penting yaitu notifikasi dan replikasi yang diberikan oleh suatu event. Akan tetapi, dari sisi service, event ini akan membawa kelebihan louse coupling yang lebih tinggi daripada command dan query.
Event untuk Notifikasi
Hampir semua message broker menyediakan layanan publisher dan subscribe dimana message diarahkan bukan oleh publisher tetapi lebih kepada consumer atau receiver. Proses ini dikenal dengan receiver-driven routing. Dampak dari ini membuat consumer mengontrol keberadaannya pada interaksi publisher dan consumer. Akhir-akhirnya membuat sistem menjadi plugable.
Kita ambil contoh pada pembelian di situs e-commerce tertentu. Pada saat customer menekan button pembelian dan permintaan terkirim ke service Order dan setidaknya tiga hal ini akan terjadi.
- Service pengiriman akan diberikan notif atau informasi
- Pencarian alamat dari pembeli
- Proses pengiriman barang di mulai.
Pada sistem berbasis request response menggunakan REST atau RCP kira-kira prosesnya dapat digambarkan seperti berikut.
Apabila proses order di atas kita lakukan dengan pendekatan event base maka event akan dikirim ke message broker (terjadi pembelian barang) dan akan ditanggapi minimal oleh Shipping service.
Apabila kita analisis lebih dalam proses pembelian barang tidak banyak berubah cuma yang asalnya komunikasi antara Order service dan Shipping service yang awalnya saling call satu sama lain secara langsung diganti menggunakan event base komunikasi. Akan tetapi ada satu hal perubahan penting, yakni Order service tidak mengetahui bahwa terdapat Shipping Service. Order hanya mengirimkan event kejadian berupa permintaan pembelian barang.
Shipping service sekarang menjadi memiliki kendali apakah dia akan terlibat diproses order atau tidak. Jadi, logic pemrograman adanya di bagian penerima bukan di bagian pengirim.
Apabila sistem menjadi lebih kompleks maka kemampuan plugable ini mejadi lebih penting. Misal jika kita memperluas sistem dengan menambhkan service re-pricing yang akan mengupdate harga barang secara real time berdasarkan penawaran dan permintaan.
Pada pendekatan request respon kita perlu membuat satu method tambahan untuk mengupdate harga barang yang dipanggil oleh Order service dan Payment service. Sedangkan pada event base penetapan harga hanyalah layanan (service) yang bisa kita hubungkan pada flow proses yang sedang terjadi sesuai dengan kriteria tentunya.
Event — State Transfer
Apabila kita perhatikan gambar di atas baik untuk proses event driven ke Shipping service atau pada penambahan Re-pricing service masih terdapat satu proses yang berbasis request response yaitu proses query ke customer service untuk meminta alamat dari customer.
Kita dapat juga menggunakan event driven sebagai type dari stare transfer. Daripada kita meminta data ke customer service maka kita bisa melakukan replikasi data secara stream data (seperlunya) dari customer service ke shipping service. Dengan demikian, shipping service dapat melakukan pencarian data customer secara local.
Dalam proses replikasi data perlu diperhatikan juga mengenai data integrasi dan data integritas. Pilihlah data yang memamg diperlukan dan jangan lupa perhatikan bounded context antar keduanya.
Pemilihan Pendekatan
Berikut adalah kelebihan pemilihan event drvien dengan notifikasi dan state transfer
- Isolasi dan autonomi. Isolasi itu diperlukan untuk autonomi. Menjaga data yang dibutuhkan untuk query tetap terisolasi dan local berarti kita tetap menjaga kontrol dari service.
- Data akses yang cepat. Local data pastinya akan lebih cepat. Ini pasti benar ketika kita memerlukan penggabungan data dari beberapa service. apalagi jika query terlibat pada beberapa service yang terpisah secara geografi.
- Data tersedia pada offline. Untuk kasus-kasus mobile phone, kereta api, pesawat, atau sejenisnya dengan memiliki data replikasi ketika offline sungguh sangat baik dan ketika online lagi kita dapat melakukan singkronisasi.
Adapun berikut adalah beberapa kelebihan dari pemilihan request response.
- Simple.Mudah dan sangat simple untuk diimplementasikan. Tidak ada bagian-bagian yang bergerak dan tidak ada state yang harus diatur.
- Singleton. State hanya berada dalam satu tempat (satu thread) sehingga semua sistem dan user melihat perubahan secara serempak. Sangat penting untuk kasus-kasus yang sangat memerlukan singkronisasi. Sebagi contoh perubahan saldo user.
- Control terpusat. Flow proses yang terpusat dapat digunakan untuk memusatkan proses bisnis dalam satu layanan service. Hal ini lebih mudah untuk dalam segala hal apapun.
Tentui saja kedua solusi seperti sebelumnya dapat kita gunakan secara bersama-sama dan tergantung pada keperluan yang kita fokuskan. Jika kita mendesign untuk kasus penggunaan yang kecil dan sederhana maka cukup kita menggunakan event drivent pada notifikasi. Adapun untuk proses yang sangat besar dan komplek maka penambahan event driven dengan replikasi dapat kita gunakan agar sistem meiliki tinggak autonomi yang lebih tinggi. Rata-rata jika kita menggunakan microservce akan cendrung menggunakan gabungan kedua implementasi darui event driven ini.
Communication between microservices needs to be based on asynchronous message passing (while logic inside each microservice is performed in a synchronous fashion)
“Jonas Boner “ — Reactive Microservice Architecture
Event Collaboration Pattern
Untuk membangun service menggunakan event driven biasanya kita dapat menerapkan pola atau pattern yang dikenal sebagai Event Collaboration Pattern. Ini memungkinkan beberapa service berkolaborasi satu sama lain dalam satu bisnis flow, dengan cara listen dari beberapa event
Kunci utama dari pattern ini adalah tidak adanya kepemilikan satu service terhadap keseluruhan proses. Sebagai gantinya semua service memiliki sebagian kecil state dari transisi flow dan dihubungkan satu sama lain melalui event.
Jika suatu service telah melakukan tugasnya, dia akan memproduce event terkait hal yang telah dia bereskan. Jika proses pembayaran dilakukan dia akan memproduce event pembayaran di proses dan seterusnya. Satu event akan mentriger langkah selanjutnya yang akan didengar oleh service nya sendiri atau beberapa service lainnya.
Apabila event kolaborasi ini di pergunakan untuk proses yang harus memperhatikan keuntuhan data maka kita masuk ke pattern yang lebih komprehensif dalam menjaga konsistensi data. Saga Pattern adalah pattern yang dapat menggunakan event kolaborasi dalam komunikasinya. Penjelasan lebih dalam mengenai saga pattern ini dapat dibaca didua artikel berikut.
- https://medium.com/the-legend/saga-pattern-f46c989dc452
- https://medium.com/the-legend/saga-pattern-dengan-command-atau-orkestrasi-2b0b76d966b6
Event dan Stream Prosessing
Dualisme antar notifikasi dan replikasi sebagai implementasi dari event akan mengarahkan pada dua konsep stream proses yaitu stateless dan stateful. Cara terbaik untuk memahaminya kita adalah dengan mencoba service yang telah kita diskusikan di atas dengan Kafka Stream API.
Pada pedekantan stateful kita replikasi tabel Customer ke dalam Kafka Stream API misalkan Ktable. Dengan stateful kita dapat mengimplementasikan state transper implementasi.
Adapun pada pendekatan stateless kita sama menggunakan Kafka Stream API tetapi tidak ada proses replikasi table customer sehingga kalau ada keperluan Kafka Stream API meminta data ke Customer Service.
Penjelasan lebih detil mengenai kedua stream proses ini akan kita bahas di artikel tersendiri mengenai Event Prosessing.
Menggabungkan Request dan Event Driven
Pendekatan yang sangat umum dalam menggabungkan request dan event driven dapat digambarkan seperti berikut.
Request dari client atau user menggunakan REST API dan komunikasi satu service dengan service lainnya akan menggunakan Kafka serta mengimplementasikan event driven.
Adapun legacy aplikasi akan berkomunikasi menggunakan Kafka conect sehinga data dapat di kirim ke Kafka tanpa sedikitpun perubahan kode pada aplikasi legasi tersebut. Penjelasan lebih dalam mengenai Kafka conect dan beberapa implementasinya dapat di baca di beberapa artikel berikut
- https://medium.com/the-legend/kafka-connect-dan-debezium-4e9b44f3179
- https://medium.com/the-legend/debezium-94e9b68580c9
Pada implemetnasi yang lebih besar, service-service ini cenderung dan memang dirancang berkelompak satu sama lain berdasarkan bisnis model masing-masing. Satu bisnis model yang terdiri banyak service akan berkomunkasi menggunakan Kafka dan antar cluster akan berkomunikasi menggunkan Kafka yabng lain seperti gambar berikut.
Satu bisnis model dengan bisnis model lainya akan tersabung dengan bounded context dan penerapannya menggunakan domain driver design (DDD). Penjelasan lebih dalam mengenai DDD dan bounded context pada microservice implementasi dapat dibaca di artiket berikut.
- https://medium.com/the-legend/strategi-mengurai-monolith-menjadi-microservice-bd214db012a5
- https://medium.com/the-legend/data-management-pada-microservice-a958ab5e63d2
Apa Selanjutanya
Pada pembahasan di atas kita sudah mulai membahas lebih dalam mengenai penggunakan Kafka dalam event driven arsiterktur. Selanjuutnya kita akan membahas lebih dalam mengenai Event Prosessing yang sempat dibahas sekilas. Stay Tuned aja!
References
- Adam Bellemare. 2020. Building Event-Driven Microservices. USA: O’Reilly Media, Inc.
- Escoffier, Clement. 2017. Building Reactive Microservices in Java. USA: O’Reilly Media, Inc.
- Stopford, Ben. 2018. Designing Event-Driven System. USA: O’Reilly Media, Inc.
- Boner, Jonas. 2016. Reactive Microservice Architecture. USA: O’Reilly Media, Inc.
Sponsor
Membutuhkan kaos dengan tema pemrograman :
Dapat menghubungi The Legend.