Apa cara yang tepat untuk menyinkronkan data di seluruh layanan microser?

19

Saya relatif baru dalam arsitektur layanan mikro. Kami memiliki aplikasi web berukuran sedang dan saya menimbang pro dan kontra memecahnya menjadi layanan microser, bukan sistem monolitik yang kami miliki sekarang bergerak maju.

Sejauh yang saya mengerti, pertimbangkan microservices Adan Bmasing-masing mengandalkan subset data yang dimiliki oleh yang lain. Jika sebuah pesan diposkan dengan Amengatakan bahwa sesuatu telah berubah, Bdapat menggunakan pesan itu dan mereplikasi salinan lokal Ainfo dan menggunakannya untuk melakukan apa pun yang Bperlu dilakukan.

Namun, bagaimana jika Bturun / gagal dan setelah beberapa saat, muncul kembali. Selama waktu itu, Atelah menerbitkan dua pesan lagi. Bagaimana cara Bmengetahui cara memperbarui salinan Ainfo lokalnya ?

Memang, jika Bhanya konsumen dari Aantrian, maka ia dapat mulai membacanya begitu kembali online tetapi bagaimana jika ada konsumen lain dari antrian itu dan pesan-pesan itu dikonsumsi?

Sebagai contoh yang lebih konkret, jika suatu Userslayanan memperbarui alamat emailnya sementara layanan Billingmikro turun, jika layanan Billingmikro muncul kembali, bagaimana ia tahu bahwa email telah diperbarui?

Ketika layanan microser muncul kembali, apakah ia melakukan siaran yang mengatakan, "Hai, saya kembali, berikan saya semua info Anda saat ini?"

Secara umum apa yang akan menjadi praktik industri terbaik untuk sinkronisasi data?

bangsawan
sumber
1
Untuk menghindarinya sedapat mungkin.
Telastyn
1
Mengapa Ordersperlu tahu tentang Users?
kdgregory
Itu hanya sebuah contoh. Ganti keduanya dengan apa pun yang Anda inginkan yang masuk akal.
noblerare
Penggemar perutean akan memecahkan masalah 'pesan Anda dikonsumsi oleh orang lain'. tetapi benar-benar tidak jelas apa yang ingin Anda capai.
Ewan
@ Ewan Saya telah memperbarui posting asli saya untuk lebih menjelaskan apa yang saya coba tanyakan.
noblerare

Jawaban:

5

Saya akan menantang seluruh gagasan Anda tentang "mendorong data ke semua layanan microser lainnya".

Biasanya, jika layanan penagihan membutuhkan alamat email, ia hanya meminta layanan alamat untuk alamat email pelanggan tertentu. Tidak perlu memiliki salinan dari semua data alamat dan tidak akan diinformasikan jika ada perubahan. Itu hanya bertanya dan mendapat jawaban dari data terbaru.

J. Fabian Meier
sumber
Saya pikir jawaban ini sangat tepat. Ini menghilangkan banyak masalah yang berkaitan dengan sinkronisasi. Bahkan, saya melihat kode sekarang yang memiliki masalah seperti itu karena berbagai layanan menyimpan salinan informasi dan memiliki masalah sinkronisasi tersebut.
DaveG
2
Terima kasih atas jawaban anda. Jadi mengapa ada kebutuhan untuk model pub / sub dan antrian pesan? Jika kami mencoba "menarik" alih-alih "mendorong" data, kami khawatir tentang latensi layanan.
mulia
AFAIK, layanan Anda tidak perlu bereaksi segera jika ada perubahan (seperti di pub / sub), tetapi kadang-kadang membutuhkan data. Maka saya hanya akan menariknya. Jika Anda khawatir tentang latensi, Anda dapat men-cache data, tetapi ini sekali lagi harus dibayar dengan tidak mengetahui apakah data tersebut mutakhir. Jika file Anda besar, Anda juga dapat menanyakan apakah ada perubahan sebelum menarik sesuatu lagi.
J. Fabian Meier
Ingatlah bahwa solusi ini dikenakan biaya untuk menggabungkan layanan dependen, yang berarti alamat e-mail tidak akan tersedia ketika layanan pengguna tidak tersedia. Salah satu ide awal untuk memecah layanan untuk memulainya sehingga mereka dapat digunakan secara independen, dapat diskalakan, dll. Jika semua layanan dikomunikasikan secara langsung satu sama lain tanpa cache atau jaminan ketersediaan tinggi maka ketika satu sistem mati, mereka semua turun.
dukethrash
@dukethrash Kemudian buat itu sangat tersedia.
J. Fabian Meier
5

Setelah melakukan sedikit riset lebih lanjut, saya menemukan artikel ini dari mana saya menarik beberapa kutipan yang menurut saya bermanfaat untuk apa yang ingin saya capai (dan untuk pembaca masa depan). Ini menawarkan cara untuk mengadopsi model pemrograman reaktif daripada model pemrograman imperatif.

Sumber acara

Idenya di sini adalah untuk mewakili transisi keadaan setiap aplikasi dalam bentuk peristiwa yang tidak berubah. Acara kemudian disimpan dalam bentuk log atau jurnal saat terjadi (juga disebut sebagai 'acara toko'). Mereka juga dapat ditanyakan dan disimpan tanpa batas, bertujuan untuk mewakili bagaimana keadaan aplikasi, secara keseluruhan, berkembang seiring waktu.

Apa yang membantu ini capai adalah bahwa jika suatu layanan mikro turun namun peristiwa lain yang berkaitan dengannya sedang diterbitkan dan peristiwa-peristiwa dikonsumsi oleh, katakanlah, contoh-contoh lain dari layanan mikro itu, ketika layanan mikro itu muncul kembali, itu dapat merujuk pada ini event storeuntuk mengambil semua peristiwa yang terjawab selama periode itu turun.

Apache Kafka sebagai Perantara Acara

Pertimbangkan penggunaan Apache Kafka yang dapat menyimpan dan mengirim ribuan acara per detik dan memiliki mekanisme replikasi dan toleransi kesalahan yang terintegrasi. Ini memiliki penyimpanan peristiwa yang dapat disimpan di disk tanpa batas dan dikonsumsi kapan saja (tetapi tidak dihapus) dari Topik (antrian mewah Kafka) dikirim ke.

Peristiwa tersebut kemudian ditetapkan offset yang secara univokal mengidentifikasinya dalam Topik - Kafka dapat mengelola offset itu sendiri, dengan mudah menyediakan semantik pengiriman "paling banyak sekali" atau "setidaknya satu kali", tetapi mereka juga dapat dinegosiasikan ketika konsumen acara bergabung dengan suatu Topik. , memungkinkan layanan microser untuk mulai mengkonsumsi acara dari tempat yang sewenang-wenang dalam waktu - biasanya dari tempat konsumen berhenti. Jika offset peristiwa yang dikonsumsi terakhir secara transaksi tetap ada di penyimpanan lokal layanan ketika usecases 'berhasil menyelesaikan', offset itu dapat dengan mudah digunakan untuk mencapai semantik pengiriman acara “tepat sekali”.

Bahkan, ketika konsumen mengidentifikasi diri mereka ke Kafka, Kafka akan merekam pesan mana yang dikirimkan ke konsumen mana sehingga tidak melayani lagi.

Sagas

Untuk usecase yang lebih kompleks di mana komunikasi antara layanan yang berbeda memang diperlukan, tanggung jawab untuk menyelesaikan usecase harus dikenali dengan baik - usecase didesentralisasi dan hanya selesai ketika semua layanan yang terlibat mengakui tugas mereka berhasil diselesaikan, jika tidak seluruh usecase harus gagal dan tindakan korektif harus dipicu untuk mengembalikan negara lokal yang tidak valid.

Saat itulah saga ikut bermain. Saga adalah urutan transaksi lokal. Setiap transaksi lokal memperbarui basis data dan menerbitkan pesan atau peristiwa untuk memicu transaksi lokal berikutnya dalam kisah tersebut. Jika transaksi lokal gagal karena melanggar aturan bisnis maka hikayat tersebut melakukan serangkaian transaksi kompensasi yang membatalkan perubahan yang dilakukan oleh transaksi lokal sebelumnya. Baca ini untuk info lebih lanjut.

bangsawan
sumber
Saya masih tidak mengerti mengapa Anda ingin membangun struktur yang begitu rumit. Biasanya lebih mudah jika setiap layanan hanya menyimpan datanya sendiri dan memberikannya ke layanan lain berdasarkan permintaan.
J. Fabian Meier
^ Tetapi itu akan mengurangi ketersediaan sistem. Struktur yang rumit mungkin diperlukan jika ketahanan tinggi diperlukan.
avmohan
1

Bahkan jika saya terlambat, saya akan mengajukan 2 sen saya pada argumen karena saya pikir itu poin penting ketika Anda ingin mengevaluasi e merancang arsitektur microservices yang digerakkan oleh peristiwa. Setiap microservice tahu persis peristiwa apa yang berdampak pada keadaannya dan dapat menunggu mereka. Ketika layanan Microsoft tidak tersedia, harus ada komponen yang menyimpan pesan yang diperlukan dari layanan Microsoft yang gagal hingga tidak dapat "mengkonsumsinya". Ini sebenarnya adalah model "produsen / konsumen" dan bukan "publikasikan / berlangganan". Pialang pesan (seperti Kafka, RabbitMQ, ActiveMQ dll.) Biasanya merupakan cara terbaik untuk mencapai perilaku ini (kecuali jika Anda tidak mengimplementasikan sesuatu yang berbeda seperti event sourcing) menyediakan antrian persisten dan mekanisme ack / nack.

Sekarang layanan mikro tahu bahwa suatu pesan pada akhirnya dikirimkan tetapi itu tidak cukup: yang mana ia mengharapkan pengiriman satu pesan? dapatkah ia mengelola pengiriman beberapa salinan dari pemberitahuan acara yang sama? Ini masalah pengiriman semantik (setidaknya sekali, tepat sekali)

Pemikiran akhir:

  1. Ketika Anda menambahkan microservice ke arsitektur Anda yang perlu mengkonsumsi acara dari orang lain, Anda harus melakukan sinkronisasi pertama

  2. Bahkan broker dapat gagal, dalam hal ini pesan hilang

untuk kedua skenario, akan bermanfaat untuk memiliki mekanisme sederhana untuk menghidrasi ulang kondisi layanan mikro Anda. Itu bisa berupa REST API atau skrip yang mengirim pesan, tetapi yang paling penting adalah memiliki sarana untuk melakukan beberapa tugas pemeliharaan

Carmine Ingaldi
sumber
0

Anda dapat mengganti antrian acara normal dengan model penerbit / pelanggan, di mana Alayanan mempublikasikan pesan baru topik T dan Bjenis layanan mikro akan berlangganan ke topik yang sama.

Idealnya Badalah layanan tanpa kewarganegaraan, dan itu akan menggunakan layanan ketekunan yang terpisah, sehingga Bcontoh layanan yang gagal akan diganti dengan menelurkan satu atau lebih Bcontoh layanan untuk melanjutkan pekerjaannya, membaca dari layanan ketekunan bersama yang sama.

A.Rashad
sumber
0

Jika sebuah pesan diposting oleh A yang mengatakan bahwa sesuatu telah berubah, B dapat mengkonsumsi pesan itu dan mereplikasi salinan lokal dari informasi A dan menggunakannya untuk melakukan apa pun yang perlu dilakukan oleh B.

Jika Anda ingin B dapat mengakses data internal A, Anda akan lebih baik memberikannya akses ke basis data internal A.

Namun Anda tidak boleh melakukan itu, inti dari arsitektur berorientasi layanan adalah bahwa layanan B tidak dapat melihat status internal layanan A dan terbatas untuk membuat permintaan melalui REST APIs (dan sebaliknya).

Dalam kasus Anda, Anda dapat memiliki layanan data pengguna, yang memiliki tanggung jawab menyimpan semua data pengguna. Layanan lain yang ingin menggunakan data itu hanya memintanya ketika mereka membutuhkannya dan tidak menyimpan salinan lokal (yang sebenarnya sangat berguna jika Anda berpikir tentang kepatuhan GDPR). Layanan Data Pengguna dapat mendukung operasi CRUD sederhana seperti "Buat pengguna baru", atau "Ubah nama untuk pengguna_id 23" atau dapat memiliki operasi yang lebih kompleks, "Temukan semua pengguna standar dengan ulang tahun yang akan datang dalam 2 minggu ke depan dan berikan kepada mereka status uji coba premium ". Sekarang ketika layanan Penagihan Anda perlu mengirim email ke pengguna 42, ia akan meminta layanan Data Pengguna "Apa alamat email untuk user_id 42", gunakan data internalnya dengan semua informasi penagihan untuk membuat email dan kemudian dapat melewati alamat email dan isi ke server email.

Helena
sumber