Eventsourcing and CQRS Architecture using Golang, gRPC, NATS and Elasticsearch
Hi hi semua
kali ini saya bakal bikin tutorial tentang arsitektur Eventsourcing dan CQRS serta cara implementnya di golang menggunakan gRPC, NATS dan Elasticsearch
Haah Apaan tuuh ???..
eiits.. jangan bingung dulu tutorial ini saya buat sesimple mungkin biar mudah dipahami
mungkin beberapa dari kalian udah ada yang pernah dengar tentang Enventsourcing dan CQRS atau mungkin ada yang blum pernah dan baru tau sekarang
Oke, CQRS kita liat dari webnya www.cqrs.nu
CQRS means “Command-query responsibility segregation”. We segregate the responsibility between commands (write requests) and queries (read requests). The write requests and the read requests are handled by different objects.
dan eventsourcing sendiri kalo dari https://www.eventstore.com/blog/what-is-event-sourcing
alternative way to persist data. In contrast with state-oriented persistence that only keeps the latest version of the entity state, Event Sourcing stores each state mutation as a separate record called an event.
nah kita akan buat service deposit untuk create dan approve nya menggunakan arsitektur ini
oke langsung aja pertama yang harus kalian lakukan adalah clone repo berikut ke local kalian https://github.com/Aris-haryanto/CQRS-Architecture-With-Golang-gRPC-and-NATS
jika sudah silakan install tools2 yang dibutuhkan sesuai judulnya kita pake gRPC, NATS dan Elasticsearch
- untuk gRPC protobufnya kalian bisa follow guide installnya disini
- untuk NATSnya karena kita konsepnya realtime jadi kita pake NATS Streaming ya kalian bisa follow guide installnya disini
- untuk elasticsearchnya kebetulan saya menggunakan MAC bisa ikutin guide untuk installnya disini
- untuk library pendukung golangnya kalian perlu masuk dulu kedirectory yang tadi sudah diclone kemudian kalian ketik diterminal seperti ini
go get -v ./...
jika sudah semua pastikan koneksi database MySQLnya sudah sesuai
kemudian jalankan semua servicenya yah
$ nats-streaming-server
$ elasticsearch$ go run client/main.go
$ go run serives/main.go
$ go run deposit-create/main.go
$ go run deposit-approve/main.go
$ go run log/main.go
oke lanjut, disini saya gambarin flownya dulu yah
berikut adalah arsitektur yang akan kita buat dalam tutorial ini
kalo kamu sudah clone reponya maka akan terlihat structure directory seperti ini
Saya coba jelaskan fungsi dari masing-masing structure directory diatas sesuai nomer diagramnya
- Service Client
service ini ada pada directory/client
. disini adalah service yang menerima request dari User melalui API kemudian dilempar ke gRPC
dibagian ini validasi harus sedetail mungkin, misal seperti pengecekan apakah data yang diinput sudah ada atau belum, pengecekan input string atau integer dan lainnya. agar mengurangi error sistem saat melakukan inserting kedatabase. kalaupun ada yang terlewat kita bisa melakukan push notif ke user bahwa input yang dia masukan salah dan meminta mereka input ulang, tapi ini wasting time! sebisa mungkin kita harus cegah ini diawal ya - gRPC
service ini ada pada directory/proto
. dibagian ini adalah proses yang untuk menghubungkan antara Service Client dengan Service Server menggunakan gRPC. kenapa harus gRPC ?
menurut saya pribadi gRPC lebih cocok digunakan untuk komunikasi antar service (tapi untuk komunikasi frontend seperti React/Vue/Nuxt ke service (backend) yes! you still need REST API),
kemudian dalam hal kecepatan yang “katanya” lebih cepat dari REST karena dia menggunakan Protocol Buffer dan HTTP/2, kalian boleh baca disini untuk komparasinya
kalian bisa update bagian ini jika ingin menambahkan parameter baru atau fungsi baru pada file/proto/*.proto
kemudian generate menggunakan command berikut$ protoc -I proto/ proto/*.proto --go_out=plugins=grpc:proto
- Service Server
service ini ada pada directory/services
. dimana proses server menerima request dari gRPC yang dikirim dari Service Client disini harus dipastikan bahwa data yang dikirim harus masuk ke eventstore agar kita bisa memberi response ke user apakah proses ini gagal atau berhasil
*Notes:point dari Eventsourcing adalah user tidak menunggu sampai semua proses selesai tapi hanya memastikan proses itu sudah masuk (ke eventstore)
, untuk berhasil atau tidaknya request user kita akan notif mereka menggunakan service semacam push notif (tapi tidak ada di tutorial ini yah hehe) - Eventstore
bagian ini ada dalam directory/services
. dan memanggil function ke/database/eventstore
. ketika Service Server menerima request maka system perlu insert ke eventstore, eventstore disini adalah data-data yang dikirim dari client kemudian kita simpan ke database, kenapa perlu disimpan ?
jika terjadi kegagalan sistem pada proses maka data request tidak hilang dan kita bisa proses ulang (merekonstruksi) sesuai dengan event yang gagal berdasarkan aggregate_idnya
jadi Eventstore ini bisa dikatakan sebagai checkpoint pada sistem
*Remember:lost your data mean lost your money
*Notes:rekomendasinya untuk eventstore ini disimpan ke NoSql ya agar lebih cepat proses insertnya, hanya saja ditutorial ini saya simpan ke database agar lebih mudah dibacanya
- Publish Event
service ini ada pada directory/nats
. dibagian ini dimana request dari client dipublish menggunakan NATS Streaming semua service yang listen ke masing2 channel akan tertriger untuk melakukan processnya - Deposit Create & Deposit Approve
service ini ada pada directory/deposit-create
dan/deposit-approve
. diservice ini kita melisten ke channeldeposit-created
dandeposit-approve
sesuai channelnya maka kita akan meng-create atau meng-approve deposit dari client, disini kita perlu mengincludeagregate-id
dari eventstore ke data yang diinsert agar kita bisa tau event mana yang relate dengan data tersebut melaluiagregate-id
. dan ketika kita melakukan update atau delete, kita perlu insertagregate-id
yang sama ke eventstore.
khusus untuk Deposit Approve kalian bisa membuat service baru misal Service Admin yang terhubung ke gRPC untuk handle deposit-approve dari sisi admin. tapi dalam tutorial ini saya gabungkan ke Service Client agar lebih simple - LOG
service ini ada pada directory/log
. ketika publish event ke channel tertentu pastikan kalian publish juga ke channelLog
untuk mentrace jalannya system kalian - Elasticsearch
bagian ini ada dalam directory/database/command.go
. ketika deposit created/approve maka kalian harus update ke 2 object data yang pertama ke elasticsearch dan yang kedua ke Database aslinya, well disinilah point dari CQRS ini, kenapa harus update ke 2 object ?
ketika kalian write maka proses itu mungkin butuh waktu untuk write ke db (delay), dan kalian tidak bisa hanya memanfaatkan db replica karena inipun ada delay
mungkin tidak terasa jika kita write hanya puluhan atau ratusan data, tapi bagaimana jika jutaan data mungkin jeda ini akan ada dan tentunya kita tidak bisa langsung membaca data tersebut
kita perlu 1 object lagi yang cepat disini saya memilih elasticsearch.
kalian bisa baca disini untuk benchmarknya
Notes: khusus untuk request Read dari Service Server kita langsung baca ke Elasticsearch tanpa melalui event
Oke mungkin sampai sini dulu sharingnya untuk tutorial kali ini
semoga bisa bermanfaat
jika kalian suka silakan di clap dan share artikel ini
Terimakasih