Salah satu masalah utama yang saya lihat terjadi dalam sistem dengan layanan microser adalah cara transaksi bekerja ketika mereka menjangkau berbagai layanan. Dalam arsitektur kami sendiri, kami telah menggunakan transaksi terdistribusi untuk menyelesaikan ini, tetapi mereka datang dengan masalah mereka sendiri. Terutama kebuntuan telah menjadi rasa sakit sejauh ini.
Pilihan lain tampaknya adalah semacam manajer transaksi yang dibuat khusus, yang mengetahui aliran dalam sistem Anda, dan akan menangani pengembalian untuk Anda sebagai proses latar belakang yang mencakup seluruh sistem Anda (sehingga akan memberi tahu layanan lain untuk mengembalikan dan jika mereka down, beri tahu mereka nanti).
Apakah ada opsi lain yang diterima? Keduanya tampaknya memiliki kekurangan. Yang pertama dapat menyebabkan kebuntuan dan banyak masalah lainnya, yang kedua dapat menyebabkan inkonsistensi data. Apakah ada opsi yang lebih baik?
sumber
Jawaban:
Pendekatan yang biasa adalah mengisolasi layanan-layanan mikro itu sebanyak mungkin - memperlakukan mereka sebagai satu unit. Kemudian transaksi dapat dikembangkan dalam konteks layanan secara keseluruhan (yaitu bukan bagian dari transaksi DB biasa, meskipun Anda masih dapat memiliki transaksi DB internal ke layanan).
Pikirkan bagaimana transaksi terjadi dan jenis apa yang masuk akal untuk layanan Anda kemudian, Anda dapat menerapkan mekanisme rollback yang membatalkan operasi aslinya, atau sistem komitmen 2 fase yang menyimpan operasi asli hingga diminta untuk melakukan komit secara nyata. Tentu saja kedua sistem ini berarti Anda menerapkannya sendiri, tetapi kemudian Anda sudah menerapkan layanan-mikro Anda.
Jasa keuangan melakukan hal semacam ini sepanjang waktu - jika saya ingin memindahkan uang dari bank saya ke bank Anda, tidak ada transaksi tunggal seperti yang Anda miliki dalam DB. Anda tidak tahu sistem apa yang dijalankan bank mana pun, jadi harus secara efektif memperlakukan masing-masing seperti layanan mikro Anda. Dalam hal ini, bank saya akan memindahkan uang saya dari akun saya ke rekening holding dan kemudian memberi tahu bank Anda bahwa mereka punya uang, jika pengiriman gagal, bank saya akan mengembalikan akun saya dengan uang yang mereka coba kirim.
sumber
Saya pikir kebijaksanaan standar adalah tidak pernah melakukan transaksi lintas batas layanan-mikro. Jika set data tertentu benar-benar perlu konsisten secara atom dengan yang lain, kedua hal itu menjadi satu.
Ini adalah salah satu alasan mengapa sangat sulit untuk membagi sistem menjadi layanan sampai Anda telah mendesainnya sepenuhnya. Yang di dunia modern mungkin berarti menuliskannya ...
sumber
Saya pikir jika konsistensi adalah persyaratan kuat dalam aplikasi Anda, Anda harus bertanya pada diri sendiri apakah layanan mikro adalah pendekatan yang lebih baik. Seperti yang dikatakan Martin Fowler :
Tetapi mungkin dalam kasus Anda, Anda dapat mengorbankan Konsistensi dalam posisi Ketersediaan
Namun saya juga bertanya pada diri sendiri apakah ada strategi untuk transaksi terdistribusi di layanan mikro, tetapi mungkin biayanya terlalu tinggi. Saya ingin memberi Anda dua sen saya dengan artikel Martin Fowler dan teorema CAP yang selalu luar biasa .
sumber
Seperti yang disarankan dalam setidaknya satu jawaban di sini tetapi juga di tempat lain di web, dimungkinkan untuk merancang satu layanan mikro yang bertahan entitas bersama dalam transaksi normal jika Anda memerlukan konsistensi antara kedua entitas.
Tetapi pada saat yang sama, Anda mungkin memiliki situasi di mana entitas benar-benar tidak termasuk dalam layanan mikro yang sama, misalnya, catatan penjualan dan catatan pemesanan (ketika Anda memesan sesuatu untuk memenuhi penjualan). Dalam kasus seperti itu, Anda mungkin memerlukan cara untuk memastikan konsistensi antara kedua layanan mikro.
Transaksi yang didistribusikan secara tradisional telah digunakan dan dalam pengalaman saya, mereka bekerja dengan baik sampai skala ke ukuran di mana penguncian menjadi masalah. Anda dapat mengendurkan penguncian sehingga benar-benar hanya sumber daya yang relevan (mis. Barang yang dijual) "dikunci" menggunakan perubahan negara, tetapi ini adalah di mana ia mulai menjadi rumit karena Anda memasuki wilayah di mana Anda perlu membangun semua logika untuk melakukan ini, sendiri, daripada memiliki, katakanlah database yang menanganinya untuk Anda.
Saya telah bekerja dengan perusahaan-perusahaan yang telah kehilangan arah untuk membangun kerangka kerja transaksi mereka sendiri untuk menangani masalah yang kompleks ini, tetapi saya tidak merekomendasikannya karena mahal dan membutuhkan waktu untuk matang.
Ada beberapa produk di luar sana yang dapat dibaut ke sistem Anda yang menjaga konsistensi. Mesin proses bisnis adalah contoh yang baik dan mereka biasanya menangani konsistensi pada akhirnya dan dengan menggunakan kompensasi. Produk lain bekerja dengan cara yang sama. Anda biasanya berakhir dengan lapisan perangkat lunak di dekat klien, yang berkaitan dengan konsistensi dan transaksi serta panggilan (mikro) layanan untuk melakukan pemrosesan bisnis yang sebenarnya . Salah satu produk tersebut adalah konektor JCA generik yang dapat digunakan dengan solusi Java EE (untuk transparansi: Saya penulisnya). Lihat http://blog.maxant.co.uk/pebble/2015/08/04/1438716480000.html untuk perincian lebih lanjut dan diskusi lebih mendalam tentang masalah yang diangkat di sini.
Cara lain untuk menangani transaksi dan konsistensi adalah dengan membungkus panggilan ke layanan mikro menjadi panggilan ke sesuatu yang transaksional seperti antrian pesan. Ambil contoh catatan penjualan / catatan pesanan dari atas - Anda bisa membiarkan layanan penjualan mikro mengirim pesan ke sistem pesanan, yang dilakukan dalam transaksi yang sama yang menulis penjualan ke database. Hasilnya adalah solusi asinkron yang berskala sangat baik. Menggunakan teknologi seperti soket web, Anda bahkan dapat mengatasi masalah pemblokiran yang sering dikaitkan dengan meningkatkan solusi asinkron. Untuk gagasan lebih lanjut tentang pola seperti ini, lihat artikel saya yang lain: http://blog.maxant.co.uk/pebble/2015/08/11/1439322480000.html .
Solusi mana pun yang akhirnya Anda pilih, penting untuk mengenali bahwa hanya sebagian kecil dari sistem Anda yang akan menulis hal-hal yang perlu konsisten - sebagian besar akses cenderung hanya-baca. Karena alasan itu, bangun manajemen transaksi hanya menjadi bagian-bagian yang relevan dari sistem, sehingga masih dapat berkembang dengan baik.
sumber
Dalam layanan microser ada tiga cara untuk mencapai konsistensi antara diff. jasa:
Orkestrasi - Satu proses yang mengelola transaksi dan rollback di seluruh layanan.
Koreografi - Layanan meneruskan pesan antara satu sama lain dan akhirnya mencapai keadaan yang konsisten.
Hibrida - Mencampur dua di atas.
Untuk bacaan lengkap, buka tautan: https://medium.com/capital-one-developers/microservices-when-to-react-vs-orchestrate-c6b18308a14c
sumber
Ada banyak solusi yang lebih mudah dikompromikan daripada yang nyaman bagi saya. Memang, jika use case Anda rumit, seperti memindahkan uang antar bank yang berbeda, alternatif yang lebih menyenangkan mungkin tidak mungkin. Tapi mari kita lihat apa yang bisa kita lakukan dalam skenario umum, di mana penggunaan layanan microser mengganggu transaksi basis data calon kami.
Opsi 1: Hindari kebutuhan transaksi jika semuanya memungkinkan
Jelas dan disebutkan sebelumnya, tetapi ideal jika kita bisa mengelolanya. Apakah komponen-komponen tersebut sebenarnya termasuk dalam microservice yang sama? Atau bisakah kita mendesain ulang sistem sehingga transaksi menjadi tidak perlu? Mungkin menerima non-transaksionalitas adalah pengorbanan yang paling terjangkau.
Opsi 2: Gunakan antrian
Jika ada cukup kepastian bahwa layanan lain akan berhasil pada apa pun yang kita inginkan, kita dapat memanggilnya melalui beberapa bentuk antrian. Item yang antri tidak akan diambil hingga nanti, tetapi kami dapat memastikan bahwa item tersebut sudah antri .
Misalnya, katakan bahwa kami ingin memasukkan entitas dan mengirim email, sebagai satu transaksi. Alih-alih memanggil server surat, kami mengantri e-mail dalam sebuah tabel.
Kelemahan yang jelas adalah bahwa beberapa layanan microser akan membutuhkan akses ke tabel yang sama.
Opsi 3: Lakukan pekerjaan eksternal yang terakhir, sesaat sebelum menyelesaikan transaksi
Pendekatan ini bertumpu pada asumsi bahwa melakukan transaksi sangat tidak mungkin gagal.
Jika kueri gagal, panggilan eksternal belum terjadi. Jika panggilan eksternal gagal, transaksi tidak pernah dilakukan.
Pendekatan ini hadir dengan keterbatasan yang kita hanya bisa membuat satu panggilan eksternal, dan itu harus dilakukan terakhir (yaitu kita tidak dapat menggunakan hasilnya dalam permintaan kita).
Opsi 4: Buat sesuatu dalam status tertunda
Seperti yang diposting di sini , kami dapat meminta beberapa layanan microser membuat komponen yang berbeda, masing-masing dalam status tertunda, non-transaksi.
Validasi apa pun dilakukan, tetapi tidak ada yang dibuat dalam keadaan definitif. Setelah semuanya berhasil dibuat, masing-masing komponen diaktifkan. Biasanya, operasi ini sangat sederhana dan kemungkinan kesalahan terjadi sangat kecil, sehingga kita bahkan dapat memilih untuk melakukan aktivasi secara non-transaksi.
Kelemahan terbesarnya adalah kita harus memperhitungkan keberadaan barang-barang yang tertunda. Permintaan pilih apa pun perlu mempertimbangkan apakah akan memasukkan data yang tertunda. Sebagian besar harus mengabaikannya. Dan pembaruan adalah cerita lain sama sekali.
Opsi 5: Biarkan microservice membagikan kuerinya
Tidak ada opsi lain yang melakukannya untuk Anda? Kalau begitu mari kita menjadi ortodoks .
Tergantung pada perusahaan, yang ini mungkin tidak dapat diterima. Aku sadar. Ini tidak lazim. Jika tidak dapat diterima, pilih rute lain. Tetapi jika ini cocok dengan situasi Anda, itu menyelesaikan masalah dengan sederhana dan kuat. Mungkin saja kompromi yang paling dapat diterima.
Ada cara untuk mengubah kueri dari beberapa layanan mikro menjadi transaksi basis data tunggal yang sederhana.
Kembalikan kueri, alih-alih menjalankannya.
Dari sisi jaringan, setiap layanan mikro harus dapat mengakses setiap basis data. Ingatlah hal ini, juga dalam hal penskalaan di masa depan.
Jika database yang terlibat dalam transaksi berada di server yang sama, ini akan menjadi transaksi reguler. Jika mereka berada di server yang berbeda, itu akan menjadi transaksi terdistribusi. Kode tetap sama.
Kami menerima permintaan, termasuk jenis koneksinya, parameternya, dan string koneksinya. Kita dapat membungkusnya dalam kelas Command yang dapat dieksekusi dengan rapi, menjaga alirannya tetap terbaca: Panggilan layanan microser di dalam Command, yang kita jalankan, sebagai bagian dari transaksi kami.
String koneksi adalah apa yang diberikan microservice asal, sehingga untuk semua maksud dan tujuan, kueri masih dianggap dijalankan oleh microservice itu. Kami hanya merutekannya secara fisik melalui microservice klien. Apakah itu membuat perbedaan? Yah, itu memungkinkan kita memasukkannya ke dalam transaksi yang sama dengan permintaan lain.
Jika kompromi dapat diterima, pendekatan ini memberi kita transaksionalitas langsung dari aplikasi monolith, dalam arsitektur layanan-mikro.
sumber
Saya akan mulai dengan menguraikan ruang masalah - mengidentifikasi batas layanan Anda . Ketika dilakukan dengan benar, Anda tidak perlu melakukan transaksi lintas layanan.
Layanan yang berbeda memiliki data mereka sendiri, perilaku, kekuatan motivasi, pemerintah, aturan bisnis, dll. Awal yang baik adalah membuat daftar kemampuan tingkat tinggi yang dimiliki perusahaan Anda. Misalnya, pemasaran, penjualan, akuntansi, dukungan. Titik awal lainnya adalah struktur organisasi, tetapi perlu diperhatikan bahwa ada peringatan - untuk beberapa alasan (politik, misalnya) mungkin bukan skema dekomposisi bisnis yang optimal. Pendekatan yang lebih ketat adalah analisis rantai nilai . Ingat, layanan Anda dapat menyertakan orang juga, itu bukan perangkat lunak semata. Layanan harus berkomunikasi satu sama lain melalui acara .
Langkah selanjutnya adalah mengukir layanan ini. Akibatnya, Anda mendapatkan agregat yang relatif independen . Mereka mewakili unit konsistensi. Dengan kata lain, internal mereka harus konsisten dan ACID. Agregat berkomunikasi satu sama lain melalui acara baik.
Jika Anda berpikir bahwa domain Anda menuntut konsistensi terlebih dahulu, pikirkan lagi. Tak satu pun dari sistem besar dan misi-kritis dibangun dengan pemikiran ini. Mereka semua didistribusikan dan pada akhirnya konsisten. Periksa kertas klasik Pat Helland .
Berikut adalah beberapa kiat praktis tentang cara membangun sistem terdistribusi.
sumber