Asumsikan kita memiliki fungsi yang memperbarui kata sandi Pengguna.
Setelah tombol 'Perbarui Kata Sandi' diklik, UpdatePasswordEvent dikirim ke topik tempat 3 layanan lain dilanggan:
- Layanan yang benar-benar memperbarui kata sandi Pengguna
- Layanan yang memperbarui riwayat kata sandi pengguna
- Layanan yang mengirimkan email yang memberi tahu pengguna bahwa kata sandinya telah diubah.
Berdasarkan dari apa yang saya mengerti tentang konsistensi akhirnya, semua layanan ini (konsumen) akan menerima acara pada saat yang sama dan memprosesnya secara terpisah yang, dalam skenario yang baik, akan menyebabkan data menjadi konsisten.
Namun, bagaimana jika layanan gagal memproses acara? mis. tiba-tiba terputus, kesalahan basis data, dll ... Apa pola / praktik yang baik untuk menangani kegagalan transaksi ini?
Saya sedang berpikir untuk membuat RollbackTopic di mana jika ada peristiwa gagal diproses, RollbackEvent akan dibuat dalam topik di mana "layanan rollback" akan melakukan tugasnya dan mengembalikan data kembali
Jawaban:
Tidak, belum tentu. Saat saya berkomentar, kami tidak dapat membatalkan email yang dikirim, jadi kami masih membutuhkan semacam "urutan". IPC lebih manajemen data-event tidak membebaskan dari orchestation 1 .
Misalnya, email tidak boleh dikirim kecuali transaksi sebelumnya selesai dengan sukses dan layanan email mendapatkan buktinya. 3
Sampaikan salam yang salah pada komputasi terdistribusi . Mereka adalah yang membuat segalanya menjadi rumit dan, seperti biasa, tidak ada peluru perak untuk berurusan dengan mereka.
Sebelum memulai perjalanan kita untuk mencari Tabut yang Hilang, kita harus mempertimbangkan untuk bertanya kepada organisasi terlebih dahulu. Seringkali solusinya adalah bagaimana organisasi menghadapi masalah ini di dunia nyata .
Apa yang semua orang (departemen) lakukan ketika data tertentu hilang atau tidak lengkap?
Kami akan menyadari bahwa departemen yang berbeda memiliki solusi berbeda yang, bersama-sama, merupakan solusi yang akan diterapkan.
Bagaimanapun, di sini ada beberapa praktik yang bisa membantu kita dengan strategi untuk diikuti.
Konsistensi akhirnya
Daripada memastikan bahwa sistem dalam keadaan konsisten sepanjang waktu, alih-alih kita dapat menerima bahwa sistem akan mendapatkannya di beberapa titik di masa depan. Pendekatan ini sangat berguna untuk operasi bisnis jangka panjang.
Cara sistem untuk mencapai konsistensi bervariasi dari satu sistem ke sistem lainnya. Ini mungkin melibatkan dari proses otomatis hingga semacam intervensi manusia. Misalnya, tipikal mencobanya lagi nanti atau kontak dengan Layanan Pelanggan .
Batalkan semua operasi
Kembalikan sistem ke kondisi konsisten melalui kompensasi transaksi . Namun, kita harus memperhitungkan bahwa, transaksi ini bisa gagal juga, apa yang bisa membawa kita ke titik di mana ketidakkonsistenan bahkan lebih sulit untuk diselesaikan. Dan, sekali lagi, kami tidak dapat membatalkan email yang dikirim.
Untuk jumlah transaksi yang rendah, pendekatan ini layak, karena jumlah transaksi kompensasi juga rendah. Jika ada beberapa transaksi bisnis yang terlibat dalam IPC, menangani satu transaksi kompensasi untuk masing-masing akan menjadi tantangan.
Jika kita pergi untuk mengkompensasi transaksi , kita akan menemukan pola desain pemutus sirkuit menjadi sangat berguna - dan wajib saya berani mengatakan -
Transaksi terdistribusi
Idenya adalah untuk menjangkau beberapa transaksi dalam satu transaksi, melalui keseluruhan proses pemerintahan yang dikenal sebagai Manajer Transaksi . Algoritma umum untuk menangani transaksi terdistribusi adalah Komitmen dua fase .
Perhatian utama transaksi terdistribusi adalah bahwa mereka bergantung pada penguncian sumber daya selama masa pakainya, dan seperti yang kita tahu, ada yang salah dengan Manajer Transaksi juga.
Jika Manajer Transaksi dikompromikan, kita dapat berakhir dengan beberapa kunci di seluruh konteks terikat yang berbeda, menghasilkan perilaku yang tidak terduga karena penyampaian pesan. 2
Operasi penguraian. Mengapa?
Sejalan dengan argumen di atas, Sam-dalam bukunya Building Microservices - menyatakan bahwa, jika kita benar-benar tidak mampu membayar konsistensi akhirnya, kita harus menghindari untuk membagi operasi sekarang.
Jika kita tidak mampu memisahkan operasi tertentu menjadi dua atau lebih transaksi, mungkin bisa dikatakan bahwa - kemungkinan - transaksi ini termasuk dalam konteks terikat yang sama, atau - setidaknya - untuk konteks lintas sektoral yang masih harus dimodelkan.
Misalnya, dalam kasus kami, kami menyadari bahwa transaksi # 1 dan # 2 terkait erat satu sama lain dan mungkin keduanya dapat memiliki konteks terikat yang sama Akun , Pengguna , Daftar , apa pun ...
Pertimbangkan menempatkan kedua operasi dalam batas-batas transaksi yang sama. Itu akan membuat seluruh operasi lebih mudah untuk ditangani. Juga menentukan tingkat kekritisan dari setiap transaksi. Mungkin, jika transaksi # 2 gagal, itu tidak boleh membahayakan seluruh operasi. Jika ragu, tanyakan kepada organisasi .
1: Bukan jenis orkestrasi yang Anda pikirkan. Saya tidak berbicara tentang orkestrasi ESB. Saya berbicara tentang membuat layanan bereaksi terhadap acara yang tepat.
2: Anda mungkin menemukan pendapat Sam Newman yang menarik tentang transaksi yang didistribusikan.
3: Periksa jawaban David Parker mengenai hal ini.
sumber
Dalam kasus Anda, Anda tidak bisa hanya memproses ketiga hal sekaligus. Yang Anda butuhkan adalah sebuah proses. Berikut adalah contoh yang sangat sederhana:
Penting untuk diketahui bahwa mengubah operasi negara HARUS selalu dibuat pada entitas yang konsisten. Kecuali Anda dapat menjamin konsistensi yang kuat , itu harus dibuat pada catatan master.
Sistem Anda harus menjamin bahwa sebelum peristiwa apa pun dimunculkan dalam perubahan sistem Anda, HARUS bertahan dengan keamanan transaksional terlebih dahulu. Ini untuk memastikan bahwa acara yang diangkat benar-benar merupakan konfirmasi dari apa yang sebenarnya terjadi.
Ada beberapa bagian rumit dari proses ini dan saya akan mengabaikan yang sudah jelas - seperti: Bagaimana jika server basis data Anda mati saat mempertahankan pengguna dengan kata sandi yang diubah? Anda cukup menerbitkan Kata Pembaruan lagi. Namun, beberapa bagian perlu dijaga oleh Anda, dan ini adalah:
Dalam suatu sistem, process orchestrator (PO) tidak lain adalah entitas lain, yang berisi keadaan internal - dalam istilah literal juga - dan memungkinkan transisi antar negara, yang secara efektif bertindak sebagai semacam mesin negara. Berkat keadaan internal Anda dapat menghapus pemrosesan duplikasi pesan.
Ketika PO berada dalam
New
kondisi dan prosesUserPasswordHasBeenUpdated
, ia mengubah statusnya menjadiUserPasswordHasBeenUpdated
(atau yang mana nama negara bekerja untuk Anda). Jika PO masih dalamUserPasswordHasBeenUpdated
dan yang lainUserPasswordHasBeenUpdated
akan tiba, PO akan sepenuhnya mengabaikan pesan, mengetahui itu duplikasi. Mekanisme serupa juga akan diterapkan untuk negara bagian lain.Menangani pengiriman e-mail sebenarnya sedikit lebih rumit. Di sini Anda memiliki dua opsi:
Kirim paling banyak sekali
Dengan opsi ini, ketika PO mencapai
UserPasswordHistoryHasBeenSaved
status, perintah untuk mengirim email dikirim sebagai reaksi terhadap perubahan status. Sistem Anda akan memastikanUserPasswordHistoryHasBeenSaved
keadaan akan tetap ada sebelum mengirim email, mis. Pesan yang digandakan tidak akan memicu pengiriman email lagi. Dengan pendekatan ini Anda memastikan bahwa keadaan yang benar disimpan untuk PO tetapi tidak dapat menjamin operasi berikut.Kirim setidaknya satu kali
Inilah yang akan saya perjuangkan.
Alih-alih menyimpan
UserPasswordHistoryHasBeenSaved
dan mengirim e-mail sebagai reaksi terhadapnya, Anda mencoba mengirim e-mail terlebih dahulu. Jika operasi pengiriman gagal, status PO tidak pernah berubahUserPasswordHistoryHasBeenSaved
dan pesan lain dari jenis yang sama masih diproses. Jika pengiriman e-mail benar-benar berhasil tetapi sistem Anda akan gagal selama mempertahankan PO dengan status barunyaUserPasswordHistoryHasBeenSaved
, pesan lainUserPasswordHistoryHasBeenSaved
akan sekali lagi memicu perintah untuk mengirim e-mail dan pengguna akan menerimanya beberapa kali. .Dalam kasus Anda, Anda ingin memastikan pengguna benar-benar menerima email. Itu sebabnya saya akan memilih opsi kedua daripada yang pertama.
sumber
Sistem antrian tidak serapuh yang Anda kira.
Jika kami menulis ketiga proses ke db relasional, kami mungkin menggunakan transaksi untuk menangani kegagalan proses pertengahan.
Tanpa komitmen akhir, pekerjaan parsial akan dibuang.
Dalam sistem basis antrian Anda akan memiliki opsi yang sama ketika Anda membaca pesan dari antrian untuk menangani kegagalan proses tengah.
Amazon SQS misalnya hanya menyembunyikan pesan yang dibaca. kecuali jika perintah Delete terakhir dikirim, pesan akan muncul kembali atau dimasukkan ke dalam antrian huruf mati.
Anda dapat menerapkan 'transaksi' serupa dengan berbagai cara, pada dasarnya memegang salinan pesan sampai Anda menerima konfirmasi pemrosesan yang berhasil. Jika konfirmasi tidak diterima tepat waktu. Anda dapat mengirim pesan lagi atau menyimpannya untuk perhatian manual.
Secara potensial Anda dapat membuat 'layanan rollback' yang memantau pesan-pesan yang salah ini, mengetahui tentang pesan terkait dan keadaan sebelumnya dan melakukan rollback.
Namun! Biasanya lebih baik hanya mengirim ulang pesan yang salah. Bagaimanapun ini cenderung menjadi kasus tepi. Baik server gagal atau ada bug dalam menangani jenis pesan tertentu.
Setelah diperingatkan akan kesalahan, layanan dapat diperbaiki dan pesan berhasil diproses. Membawa sistem secara keseluruhan kembali ke keadaan yang konsisten.
sumber
Apa yang Anda hadapi di sini adalah masalah dua jenderal . Intinya: bagaimana Anda bisa yakin pesan diterima dan respons terhadap pesan itu terjadi? Dalam banyak kasus, solusi sempurna tidak ada. Bahkan, dalam sistem terdistribusi, seringkali mustahil untuk mendapatkan pengiriman pesan yang tepat satu kali .
Komentar jelas pertama adalah bahwa layanan yang mengubah kata sandi harus mengirimkan acara perubahan kata sandi. Dengan cara ini riwayat kata sandi dan layanan pengiriman surat hanya dipicu ketika kata sandi benar-benar berubah, terlepas dari mengapa itu berubah.
Untuk benar-benar menyelesaikan masalah Anda, saya tidak akan mempertimbangkan transaksi terdistribusi, tetapi melihat ke arah pengiriman pesan setidaknya-sekali dan pemrosesan idempoten.
Setidaknya sekali
Untuk memastikan acara penggantian kata sandi benar-benar dilihat oleh semua konsumen, Anda perlu menggunakan saluran komunikasi yang tahan lama di mana pesan dapat dikonsumsi dalam gaya "setidaknya sekali". Konsumen hanya mengakui pesan yang dikonsumsi ketika mereka telah sepenuhnya memprosesnya. Jika, misalnya, layanan riwayat kata sandi macet saat menulis entri riwayat, ia akan membaca ulang acara penggantian kata sandi yang sama setelah dimulai ulang dan coba lagi, mengakui peristiwa itu sebagai hanya-baca setelah telah ditulis sendiri ke riwayat. Anda harus memilih solusi antrian pesan berdasarkan kemampuannya untuk mengirim ulang pesan sampai mereka dikenali.
Idempotensi
Setelah mencapai pengiriman minimal satu kali, ada masalah tindakan duplikat yang terjadi ketika pesan diproses sebagian sebelum konsumen terganggu dan kemudian diproses ulang di kemudian hari. Itu harus diselesaikan dengan merancang setiap layanan sehingga idempoten. Entah menulis yang dilakukan dapat terjadi beberapa kali tanpa efek samping, atau menyimpan sendiri tindakan yang diambilnya dan menghindari melakukan tindakan lebih dari sekali. Dalam hal pengiriman surat, Anda mungkin menemukan bahwa itu mungkin tidak pantas untuk membuatnya berperilaku idempoten dan baik-baik saja dengan sesekali surat yang dikirim dua kali.
Bagaimanapun, berhati-hatilah bagaimana Anda membuat layanan mikro. Apakah layanan riwayat kata sandi Anda benar-benar harus independen dari layanan perubahan kata sandi?
sumber
Saya tidak setuju dengan banyak jawaban.
Ada janji konsistensi lain yang dapat Anda tambahkan.
Konsistensi tambahan ini perlu diterapkan tergantung pada tindakan aplikasi.
Saya tidak tahu apa yang Anda maksud dengan "memperbarui sejarah" tetapi tolong jangan pernah mengubah sejarah. Jika Anda hanya memperpanjang DAG, maka ini akan menyebabkan perubahan pada kondisi saat ini. Mereka tidak mandiri. Jika demikian maka Anda tidak dapat mengandalkan sejarah yang mencerminkan apa yang terjadi. (dan yang tak kalah pentingnya, jangan menyimpan kata sandi melihat bagaimana tidak menyimpan kata sandi )
sumber
consider asking the organization first.
. Anda mungkin benar. Namun, saya merasa penting untuk mengkondisikan peristiwa yang tidak dapat kami batalkan. Misalnya pemberitahuan kepada pengguna akhir. Pemberitahuan yang berbohong tentang keadaan sebenarnya dari data pengguna mungkin memberi kesan buruk.