CQRS + Event Sourcing: (apakah benar) Perintah umumnya dikomunikasikan point-to-point, sementara Domain Events dikomunikasikan melalui pub / sub?

12

Saya pada dasarnya mencoba untuk membungkus kepala saya di sekitar konsep CQRS dan konsep terkait.

Meskipun CQRS tidak harus memasukkan Messaging dan Event Sourcing, itu tampaknya merupakan kombinasi yang baik (seperti yang dapat dilihat dengan banyak contoh / blogpost yang menggabungkan konsep-konsep ini)

Diberi kasus penggunaan untuk perubahan keadaan untuk sesuatu (katakanlah untuk memperbarui Pertanyaan tentang SO), apakah Anda menganggap aliran berikut ini benar (seperti dalam praktik terbaik)?

Sistem mengeluarkan agregat UpdateQuestionCommand yang dapat dipisahkan menjadi beberapa perintah yang lebih kecil: UpdateQuestion yang ditargetkan pada Pertanyaan Agregat Root, dan UpdateUserAction (untuk menghitung poin, dll) yang ditargetkan pada User Aggregate Root. Ini dikirim secara tidak sinkron menggunakan pengiriman pesan titik-ke-titik.

Akar agregat melakukan tugasnya masing-masing dan jika semuanya berjalan dengan baik, masing-masing, QuestionUpdated dan UserActionUpdated, yang berisi status yang di-outsourcing-kan ke Event Store .. untuk tetap bertahan yadayada, hanya untuk lengkap, tidak benar-benar intinya di sini.

Acara ini juga diletakkan di antrian pub / sub untuk penyiaran. Setiap pelanggan (di antaranya kemungkinan satu atau beberapa Proyektor yang membuat Tampilan Baca) bebas untuk berlangganan acara ini.

Pertanyaan umum: Apakah ini memang praktik terbaik, bahwa Perintah dikomunikasikan Point-to-Point (yaitu: Penerima diketahui) sedangkan acara disiarkan (Yaitu: penerima tidak diketahui)?

Dengan asumsi di atas, apa keuntungan / kerugian dari membiarkan Perintah disiarkan melalui pub / sub alih-alih point-to-point?

Sebagai contoh: Ketika menyiarkan Perintah saat menggunakan Saga bisa menjadi masalah, karena peran mediasi yang harus dimainkan Saga jika terjadi kegagalan salah satu akar agregat terhambat, karena saga tidak tahu akar agregat mana yang dimulai. .

Di sisi lain, saya melihat keuntungan (fleksibilitas) ketika perintah penyiaran diizinkan.

Geert-Jan
sumber
Pertanyaan yang ditulis dengan baik btw.
Dav

Jawaban:

19

Penafian: Saya hanya mengambil langkah pertama saya di dunia CQRS, tapi saya bisa menawarkan pemahaman saya saat ini tentang masalah ini dan kami akan melihat apakah orang lain mengonfirmasi. Semua yang saya tulis di bawah ini memiliki tema "seperti yang saya lihat", dan tidak otoritatif.

Kasus 80%

Untuk menjawab pertanyaan Anda, perintah memang merupakan urusan point-to-point. Ketika perintah memasuki controller (MVC webapp), controller itu kemudian meminta dispatcher perintah untuk menemukan satu dan hanya satu penangan perintah yang sesuai, dan mendelegasikan pekerjaan ke penangan itu.

Kenapa tidak menerbitkan?

Ini masalah tanggung jawab . Jika sesuatu mengirim perintah, itu memerlukan harapan bahwa itu akan dipenuhi. Jika Anda hanya menerbitkan dan berharap sesuatu mengambil dan menindaklanjutinya, tidak ada jaminan bahwa ini akan menjadi masalah. Dengan ekstrapolasi, Anda juga tidak tahu apakah beberapa penangan tidak memutuskan untuk bertindak berdasarkan suatu perintah, mungkin mengakibatkan perubahan yang sama diterapkan lebih dari sekali.

Acara, di sisi lain, bersifat informatif, dan masuk akal untuk mengharapkan nol, dua, atau lebih komponen untuk tertarik pada acara tertentu. Kami tidak benar-benar peduli dalam ruang lingkup untuk membuat perubahan yang diminta.

Contoh

Ini bisa dibandingkan dengan kehidupan nyata. Jika Anda memiliki tiga anak, masuk ke sebuah ruangan dan hanya berteriak "Bersihkan kamar mandi," Anda tidak memiliki jaminan bahwa seseorang akan melakukannya, dan perhaphs jika itu tidak akan dilakukan dua kali (jika Anda memiliki anak yang patuh ;-) Anda harus tarif lebih baik jika Anda menugaskan anak tertentu untuk melakukan apa yang ingin Anda lakukan.

Namun, ketika anak itu menyelesaikan pekerjaannya, akan lebih mudah jika ia berteriak "kamar mandi telah dibersihkan," sehingga semua orang yang ingin menyikat gigi tahu bahwa mereka sekarang dapat melakukannya.

Dav
sumber
sangat masuk akal. Analogi yang bagus :)
Geert-Jan
Anda kehilangan saya di .. When a command enters a controller (MVC webapp)-? Apakah Anda menggunakan RESTful? atau beberapa endpoint API hybrid? Bisakah Anda menambahkan contoh
Piotr Kula
@ppumkin kami menggunakan titik akhir WebAPI yang akan dipanggil oleh aplikasi web kami setiap kali diperlukan untuk menjalankan perintah. Misalnya. jika pengguna ingin menambahkan komentar posting, aplikasi web akan mengirim permintaan POST example.com/api/Post/AddPostComment.
Dav
1

Saya setuju bahwa sistem awal umumnya tidak akan pernah mengharapkan perintah untuk ditransaksikan oleh beberapa sistem target:

  • Perintah biasanya tidak pernah 'kirim dan salat' - sistem pemrakarsa suatu perintah biasanya menginginkan umpan balik yang tidak sinkron ketika kemajuan dan hasil dari perintah itu terjadi (mis. Acara kenegaraan seperti acknowledgement, dan berhasil completionatau failuredapat diterbitkan oleh sistem yang ditargetkan untuk memberi informasi kepada pemrakarsa itu) sistem).
  • Jika banyak sistem target terlibat, sistem inisiasi akan menerima beberapa (mungkin kontradiktif) hasil untuk perintah (mis. Target 1 berhasil, tetapi target 2 gagal). Ini akan memerlukan kompleksitas tambahan dalam menentukan keadaan aktual dari perintah asli (mis. Apakah transaksi perintah akan dianggap berhasil hanya jika semua target berhasil? Apakah perintah perlu dibatalkan atau dikompensasi dalam target yang berhasil jika salah satu target gagal? dll.) Ini akan memperkenalkan sambungan dan kompleksitas yang tidak diinginkan antara sistem awal dan target.

Namun masih ada gunanya untuk dapat berlangganan tambahan (non-transaksional, dan biasanya cukup 'promiscuous') konsumen yang 'menguping' pada perintah yang dikeluarkan antar sistem

  • Tujuan audit
  • Metrik Operasional dan Operasional (mis. Memuat, analisis bisnis, dll.)
  • Pemrosesan Kejadian yang Kompleks atau Aliran Pemrosesan Acara Aliran '- sistem ini dapat mendeteksi kesalahan atau penyimpangan dalam perintah (mis. Frekuensi perintah, atau korelasi antara berbagai kombinasi perintah dan acara), dan dapat memicu peringatan, atau tindakan perbaikan (sering kali dalam bentuk lebih lanjut, berbagai jenis perintah).
StuartLC
sumber