Ini adalah urutan umum dari dua komponen terdistribusi dalam aplikasi Java kami:
1 A sends request to B
2 B starts some job J in parallel thread
3 B returns response to A
4 A accepts response
5 Job finishes after some time
6 Job sends information to A
7 A receives response from a Job and updates
Ini adalah skenario yang ideal, dengan asumsi semuanya berfungsi. Tentu saja, kehidupan nyata penuh dengan kegagalan. Misalnya, salah satu kasus terburuk mungkin jika #6
gagal hanya karena jaringan: pekerjaan telah dijalankan dengan benar, tetapi A
tidak tahu apa-apa tentang itu.
Saya mencari pendekatan ringan tentang cara mengelola kesalahan dalam sistem ini. Perhatikan bahwa kami memiliki banyak komponen, jadi mengelompokkannya hanya karena penanganan kesalahan tidak masuk akal. Selanjutnya, saya membuang penggunaan memori / repo yang didistribusikan yang akan diinstal lagi pada setiap komponen dengan alasan yang sama.
Pikiranku menuju ke arah memiliki satu keadaan absolut pada huruf B dan tidak pernah memiliki keadaan yang tetap pada huruf a A
. Ini berarti yang berikut:
- sebelum
#1
kita tandaiA
bahwa unit kerja yaitu perubahan akan segera dimulai - hanya
B
dapat menghapus tanda negara ini. A
dapat mengambil info tentangB
kapan saja, untuk memperbarui keadaan.- tidak ada perubahan baru pada unit yang sama dapat dipanggil
A
.
Bagaimana menurut anda? Apakah ada cara ringan untuk menjinakkan kesalahan dalam sistem semacam ini?
Jawaban:
Menambahkan ke log persisten A harus cukup. Ini mengatasi dengan reboot dan partisi jaringan untuk mencapai konsistensi akhirnya, atau untuk kerusakan sinyal yang mencegah konvergensi tersebut. Dengan komit kelompok yang diamortisasi , dibutuhkan waktu kurang dari satu tulisan untuk bertahan dalam entri log.
Anda menyarankan agar B bertanggung jawab atas status yang tidak ditandai. Saya tidak setuju. Hanya A yang menyadari pekerjaan baru, dan hanya A yang harus bertanggung jawab untuk melacaknya dan melaporkan kesalahan seperti batas waktu. B mengirimkan pesan idempoten ke A, dan A memperbarui status, menanyakan ulang secara berkala sesuai kebutuhan.
Pada langkah 0, A menyadari permintaan baru dan mencatatnya. Itu merupakan kewajiban yang harus dilepaskan oleh A setelah batas waktu tertentu - A akan terus melakukan, dan mengulangi, langkah-langkah selanjutnya sampai A mengetahui bahwa pemrosesan permintaan telah selesai.
Beberapa permintaan akan lebih lama dari yang lainnya. Perkiraan waktu pemrosesan akan tersedia pada A dan B, mungkin direvisi sebagai proses yang berlanjut. Perkiraan tersebut dapat diumpankan kembali ke A sehingga jarang menghasilkan batas waktu positif palsu. Anggap saja sebagai pesan tetap hidup yang mengatakan "masih bekerja, masih bekerja"
sumber
Gunakan tarikan alih-alih strategi dorong. Buat setiap bagian menarik perubahan dari yang lain dan perbarui catatannya sendiri.
(Saya menggunakan kata antrian, tetapi Anda dapat mengganti log atau topik.)
Anda dapat memanggang antrian ke dalam layanan, atau Anda dapat memiliki pialang pesan terpisah. Implementasi yang dimasukkan ke dalam layanan dapat sesederhana
GET /jobrequests?from=<timestamp>
(dengan B mencatat cap waktu permintaan pekerjaan yang diproses terbaru).Bagian rumit dari arsitektur semacam itu adalah memutuskan semantik paling tidak satu kali vs semantik paling banyak. Konkret: jika B menarik item dari antrian dan kemudian crash saat melakukan itu, apa yang harus terjadi? Ada dua kemungkinan, dan mana yang paling tepat tergantung pada kasus penggunaan Anda:
Manfaat dari pendekatan ini:
sumber