Ruslan Aromatov, kepala pengembang, ICD
Halo, Habr! Saya bekerja sebagai pengembang backend di Moscow Credit Bank, dan selama pekerjaan saya, saya telah mendapatkan beberapa pengalaman yang ingin saya bagikan dengan komunitas. Hari ini saya akan memberi tahu Anda bagaimana kami menulis layanan cache kami sendiri untuk server depan pelanggan kami menggunakan aplikasi seluler MKB Online. Artikel ini mungkin berguna bagi mereka yang terlibat dalam desain layanan dan terbiasa dengan arsitektur layanan mikro, basis data dalam memori Tarantool dan pustaka ZeroMQ. Dalam artikel tersebut praktis tidak akan ada contoh kode dan penjelasan dasar-dasarnya, tetapi hanya deskripsi logika layanan dan interaksinya dengan contoh spesifik yang telah bekerja pada pertempuran kami selama lebih dari dua tahun.
Bagaimana semuanya dimulai
Sekitar 6 tahun yang lalu, skema itu sederhana. Sebagai warisan dari perusahaan outsourcing, kami mendapat dua klien mobile banking untuk iOS dan Android, serta server depan yang melayani mereka. Server itu sendiri ditulis dalam java, pergi ke backend dengan berbagai cara (terutama sabun), dan berkomunikasi dengan klien dengan mengirimkan xml melalui https.
Aplikasi klien dapat mengautentikasi entah bagaimana, menunjukkan daftar produk dan ... mereka tampaknya dapat melakukan beberapa transfer dan pembayaran, tetapi kenyataannya mereka tidak melakukannya dengan sangat baik dan tidak selalu. Oleh karena itu, server depan tidak mengalami sejumlah besar pengguna atau beban serius (yang, bagaimanapun, tidak mencegahnya turun sekitar sekali setiap dua hari).
Jelas bahwa kami (dan pada saat itu tim kami terdiri dari empat orang), sebagai mereka yang bertanggung jawab untuk mobile bank, tidak sesuai dengan situasi ini, dan untuk awalnya kami menertibkan aplikasi saat ini, tetapi server depan ternyata benar-benar buruk, sehingga harus cepat menulis ulang keseluruhan, secara bersamaan mengganti xml dengan json dan pindah ke server aplikasi
WildFly . Tersebar selama beberapa tahun, refactoring tidak mengacu pada pos terpisah, karena semuanya dilakukan terutama untuk memastikan bahwa sistem hanya bekerja secara stabil.
Secara bertahap, aplikasi dan server dikembangkan, mulai bekerja lebih stabil, dan fungsinya terus berkembang, yang terbayar - semakin banyak pengguna.
Pada saat yang sama, masalah seperti toleransi kesalahan, redundansi, replikasi, dan - menakutkan untuk berpikir - beban tinggi mulai muncul.
Solusi cepat untuk masalah ini adalah menambahkan server WildFly kedua, dan aplikasi belajar untuk beralih di antara mereka. Masalah pekerjaan simultan dengan sesi klien diselesaikan oleh modul
Infinispan yang diintegrasikan ke WildFly.
Tampaknya hidup semakin baik ...
Anda tidak bisa hidup seperti itu
Namun, opsi ini bekerja dengan sesi sebenarnya bukan tanpa kekurangan. Saya akan menyebutkan orang-orang yang tidak cocok dengan kita.
- Kehilangan sesi. Minus yang paling penting. Misalnya, aplikasi mengirim dua permintaan ke server-1: permintaan pertama adalah otentikasi, dan yang kedua adalah permintaan untuk daftar akun. Otentikasi berhasil, sesi dibuat di server-1. Pada saat ini, permintaan klien kedua tiba-tiba terputus karena komunikasi yang buruk, dan aplikasi beralih ke server-2, mengirimkan kembali penerusan permintaan kedua. Tetapi pada beban kerja tertentu, Infinispan mungkin tidak punya waktu untuk menyinkronkan data antar node. Akibatnya, server-2 tidak dapat memverifikasi sesi klien, mengirim respons marah kepada klien, klien sedih dan mengakhiri sesi. Pengguna harus masuk lagi. Sedih
- Restart server juga dapat menyebabkan hilangnya sesi. Misalnya, setelah pembaruan (dan ini cukup sering terjadi). Ketika server-2 mulai, itu tidak bisa berfungsi sampai data disinkronkan dengan server-1. Tampaknya server mulai, tetapi seharusnya tidak menerima permintaan. Ini tidak nyaman.
- Ini adalah modul WildFly bawaan yang mencegah kita pindah dari server aplikasi ini ke layanan microser.
Dari sini, daftar apa yang kita inginkan entah bagaimana dibentuk dengan sendirinya.
- Kami ingin menyimpan sesi klien sehingga server apa pun (tidak peduli berapa banyak) segera setelah peluncuran memiliki akses ke sana.
- Kami ingin menyimpan data klien apa pun di antara permintaan (misalnya, parameter pembayaran dan semua itu).
- Kami ingin menyimpan data arbitrer apa pun pada kunci arbitrer secara umum.
- Dan kami juga ingin menerima data klien sebelum otentikasi berlalu. Misalnya, pengguna disahkan, dan semua produknya ada di sana, segar dan hangat.
- Dan kami ingin skala sesuai dengan beban.
- Dan jalankan di buruh pelabuhan, dan tulis log pada satu tumpukan, dan hitung metrik, dan seterusnya ...
- Oh ya, dan agar semuanya bekerja dengan cepat.
Pilihan tepung
Sebelumnya, kami tidak menerapkan arsitektur layanan mikro, jadi untuk awalnya kami duduk untuk membaca, menonton, dan mencoba berbagai opsi. Sudah jelas bahwa kami membutuhkan repositori cepat dan semacam add-on yang berhubungan dengan logika bisnis dan merupakan antarmuka akses ke repositori. Selain itu, akan lebih baik untuk mempercepat transportasi cepat antar layanan.
Mereka memilih untuk waktu yang lama, banyak berdebat dan bereksperimen. Saya sekarang tidak akan menjelaskan pro dan kontra dari semua kandidat, ini tidak berlaku untuk topik artikel ini, saya hanya mengatakan bahwa penyimpanannya akan
tarantool , kami akan menulis layanan kami di java, dan
ZeroMQ akan berfungsi sebagai transportasi. Saya bahkan tidak akan berpendapat bahwa pilihannya sangat ambigu, tetapi sebagian besar dipengaruhi oleh kenyataan bahwa kami tidak menyukai kerangka kerja besar dan berat yang berbeda (untuk berat dan kelambatannya), solusi kotak (untuk keserbagunaan dan kurangnya penyesuaian), tetapi pada saat yang sama Kami senang mengendalikan semua bagian dari sistem kami sebanyak mungkin. Dan untuk mengontrol pekerjaan layanan, kami memilih server pengumpulan metrik
Prometheus dengan agen-agennya yang nyaman yang dapat dibangun ke dalam hampir semua kode. Log semua ini akan masuk ke tumpukan ELK.
Sepertinya saya sudah terlalu banyak teori.
Mulai dan selesaikan
Hasil desain kira-kira seperti skema.
PenyimpananSeharusnya sebodoh mungkin, hanya untuk menyimpan data dan status mereka saat ini, tetapi selalu bekerja tanpa restart. Dirancang untuk melayani berbagai versi server depan. Kami menyimpan semua data dalam memori, pemulihan jika restart melalui file .snap- dan .xlog.
Tabel (ruang) untuk sesi klien:
- ID sesi
- ID Pelanggan;
- versi (layanan)
- waktu pembaruan (cap waktu);
- waktu hidup (ttl);
- data sesi serial.
Semuanya sederhana di sini: klien diautentikasi, server depan membuat sesi dan menyimpannya di penyimpanan, mengingat waktu. Dengan setiap permintaan data, waktu diperbarui, sehingga sesi tetap hidup. Jika berdasarkan permintaan data ternyata sudah usang (atau tidak akan ada sama sekali), maka kami akan mengembalikan kode pengembalian khusus, setelah itu klien akan mengakhiri sesi.
Tabel cache sederhana (untuk data sesi apa saja):
- kunci;
- ID sesi
- jenis data yang disimpan (nomor sewenang-wenang);
- waktu pembaruan (cap waktu);
- waktu hidup (ttl);
- data bersambung.
Tabel data klien yang perlu dipanaskan sebelum masuk:
- ID Pelanggan;
- ID sesi
- versi (layanan)
- jenis data yang disimpan (nomor sewenang-wenang);
- waktu pembaruan (cap waktu);
- kondisi;
- data bersambung.
Bidang yang penting di sini adalah kondisi. Sebenarnya, hanya ada dua - siaga dan memperbarui. Mereka ditempatkan oleh layanan atasnya yang pergi ke backend untuk data klien sehingga contoh lain dari layanan ini tidak melakukan pekerjaan yang sama (sudah tidak berguna) dan tidak memuat backend.
Tabel Perangkat:
- ID Pelanggan;
- ID perangkat
- waktu pembaruan (cap waktu);
Tabel perangkat diperlukan sehingga bahkan sebelum klien mengotentikasi dalam sistem, cari tahu ID-nya dan mulai menerima produk-produknya (pemanasan cache). Logikanya adalah ini: pintu masuk pertama selalu dingin dengan kami, karena sebelum otentikasi kami tidak tahu klien jenis apa yang berasal dari perangkat yang tidak dikenal (klien seluler selalu mengirimkan ID perangkat dalam permintaan apa pun). Semua entri selanjutnya dari perangkat ini akan disertai dengan cache pemanasan untuk klien yang terkait dengannya.
Bekerja dengan data diisolasi dari layanan java dengan prosedur server. Ya, saya harus belajar lua, tetapi tidak butuh banyak waktu. Selain manajemen data itu sendiri, prosedur-lua juga bertanggung jawab untuk mengembalikan status saat ini, pemilihan indeks, membersihkan catatan-catatan usang dalam proses latar belakang (serat) dan pengoperasian server web built-in di mana akses layanan langsung ke data dilakukan. Ini dia - pesona menulis semuanya dengan tangan Anda - kemungkinan kendali tanpa batas. Tetapi minusnya sama - Anda harus menulis semuanya sendiri.
Tarantool sendiri bekerja dalam wadah buruh pelabuhan, semua file lua yang diperlukan diletakkan di sana pada tahap perakitan gambar. Seluruh perakitan melalui skrip gradle.
Replikasi master-slave. Di host lain, wadah yang sama persis berjalan sebagai replika penyimpanan utama. Diperlukan jika terjadi crash darurat master - maka layanan java beralih ke slave, dan itu menjadi master. Ada budak ketiga untuk jaga-jaga. Namun, bahkan kehilangan data lengkap dalam kasus kami menyedihkan, tetapi tidak fatal. Menurut skenario terburuk, pengguna harus masuk dan mengambil semua data yang lagi masuk ke cache.
Layanan JavaDirancang sebagai microservice stateless khas. Tidak memiliki konfigurasi, semua parameter yang diperlukan (dan ada 6 di antaranya) dilewatkan melalui variabel lingkungan saat membuat wadah buruh pelabuhan. Ia bekerja dengan server depan melalui transport ZeroMQ (org.zeromq.jzmq - antarmuka java ke libzmq.so.5.1.1 asli, yang kami buat sendiri) menggunakan protokol kami sendiri. Ini bekerja dengan tarantula melalui konektor java (org.tarantool.connector).
Inisialisasi layanan cukup sederhana:
- Kami memulai logger (log4j2);
- Dari variabel lingkungan (kita berada di buruh pelabuhan) kita membaca parameter yang diperlukan untuk bekerja;
- Kami memulai server metrik (dermaga);
- Hubungkan ke tarantula (asinkron);
- Kami memulai jumlah penangan benang (pekerja) yang diperlukan;
- Kami memulai broker (zmq) - siklus pemrosesan pesan tanpa akhir.
Dari semua hal di atas, hanya mesin pengolah pesan yang menarik. Di bawah ini adalah diagram microservice.
Mari kita mulai dengan dimulainya broker. Pialang kami adalah sekumpulan zmq-soket dari jenis ROUTER, yang menerima koneksi dari berbagai klien dan bertanggung jawab untuk menjadwalkan pesan yang datang dari mereka.
Dalam kasus kami, kami memiliki satu soket pendengaran pada antarmuka eksternal yang menerima pesan dari klien menggunakan protokol tcp dan yang lainnya menerima pesan dari utas pekerja menggunakan protokol inproc (ini jauh lebih cepat daripada tcp).
Setelah menginisialisasi soket, kami memulai loop acara tanpa akhir.
public int run() { int status; try { ZMQ.Poller poller = new ZMQ.Poller(2); poller.register(workerServicePoint, ZMQ.Poller.POLLIN); poller.register(clientServicePoint, ZMQ.Poller.POLLIN); int rc; while (true) {
Logika karya ini sangat sederhana: kami menerima pesan dari tempat yang berbeda dan melakukan sesuatu dengannya. Jika ada masalah dengan kami, kami keluar dari loop, yang menyebabkan proses macet, yang akan secara otomatis dimulai kembali oleh daemon buruh pelabuhan.
Gagasan utamanya adalah bahwa broker tidak berurusan dengan logika bisnis apa pun, ia hanya menganalisis header pesan dan mendistribusikan tugas ke utas pekerja yang diluncurkan sebelumnya saat layanan dimulai. Dalam hal ini, antrian pesan tunggal dengan prioritas panjang tetap membantunya.
Mari kita menganalisis algoritme menggunakan contoh skema dan kode di atas.
Setelah memulai, pekerja utas yang memulai lebih lambat dari pialang diinisialisasi dan mengirim pesan kesiapan ke pialang. Pialang menerimanya, menganalisisnya dan menambahkan setiap pekerja ke dalam daftar.
Suatu peristiwa terjadi pada soket klien - kami menerima pesan1. Pialang memanggil penangan pesan masuk, yang tugasnya adalah:
- analisis header pesan;
- menempatkan pesan di objek pemegang dengan prioritas tertentu (berdasarkan analisis header) dan masa pakai;
- menempatkan pemegang dalam antrian pesan;
- jika antrian tidak penuh, tugas pawang berakhir;
- jika antrian penuh, kami memanggil metode untuk mengirim pesan kesalahan ke klien.
Dalam iterasi yang sama dari loop, kita memanggil penangan antrian pesan:
- kami meminta pesan terbaru dari antrian (antrian memutuskan ini sendiri berdasarkan prioritas dan urutan penambahan pesan);
- periksa umur pesan (jika telah kedaluwarsa, panggil metode untuk mengirim pesan kesalahan ke klien);
- jika pesan untuk diproses relevan, cobalah untuk membuat pekerja gratis pertama siap bekerja;
- jika tidak ada, masukkan kembali pesan ke antrian (lebih tepatnya, jangan hapus saja dari sana, pesan akan hang out di sana sampai masa pakainya berakhir);
- jika kami memiliki pekerja yang siap untuk bekerja, kami menandainya sibuk dan mengiriminya pesan untuk diproses;
- hapus pesan dari antrian.
Kami melakukan hal yang sama dengan semua pesan selanjutnya. Pekerja utas itu sendiri dirancang dengan cara yang sama seperti pialang - ia memiliki siklus pemrosesan pesan tanpa akhir yang sama. Tetapi di dalamnya kita tidak lagi membutuhkan pemrosesan instan, ia dirancang untuk melakukan tugas yang panjang.
Setelah pekerja menyelesaikan tugasnya (misalnya, pergi ke backend untuk produk klien atau di tarantula untuk sesi tersebut), ia mengirim pesan ke broker, yang dikirim oleh broker tersebut ke klien. Alamat klien kepada siapa jawaban harus dikirim diingat sejak saat pesan datang dari klien dalam objek pemegang, yang dikirim ke pekerja sebagai pesan dalam format yang sedikit berbeda, dan kemudian kembali lagi.
Format pesan yang terus saya sebutkan adalah produksi kami sendiri. Di luar kotak, ZeroMQ memberi kita kelas ZMsg - pesan itu sendiri, dan ZFrame - bagian integral dari pesan ini, pada dasarnya hanya sebuah array byte, yang saya bebas gunakan jika saya mau. Pesan kami terdiri dari dua bagian (dua ZFrames), yang pertama adalah header biner, dan yang kedua adalah data (badan permintaan, misalnya, dalam bentuk string json yang diwakili oleh array byte). Header pesan bersifat universal dan bergerak dari klien ke server, dan dari server ke klien.
Faktanya, kita tidak memiliki konsep "permintaan" atau "respons", hanya pesan. Header berisi: versi protokol, tipe sistem (sistem mana yang ditangani), tipe pesan, kode kesalahan level transport (jika bukan 0, sesuatu terjadi pada mesin transfer pesan), ID permintaan (pengenal pass-through yang datang dari klien - diperlukan untuk melacak), ID sesi klien (opsional), serta tanda kesalahan tingkat data (misalnya, jika respons backend tidak dapat diuraikan, kami mengatur tanda ini sehingga parser di sisi klien tidak membatalkan respon respon, tetapi menerima data kesalahan dengan cara lain).
Berkat protokol tunggal antara semua layanan microser dan header seperti itu, kami dapat dengan mudah memanipulasi komponen layanan kami. Sebagai contoh, Anda dapat mengambil broker ke dalam proses terpisah dan menjadikannya broker pesan tunggal di tingkat keseluruhan sistem layanan-mikro. Atau, misalnya, menjalankan pekerja bukan dalam bentuk utas di dalam proses, tetapi sebagai proses independen yang terpisah. Dan sementara kode di dalamnya tidak berubah. Secara umum, ada ruang untuk kreativitas.
Sedikit tentang kinerja dan sumber daya
Broker itu sendiri cepat, dan total bandwidth layanan dibatasi oleh kecepatan backend dan jumlah pekerja. Dengan mudah, semua jumlah memori yang diperlukan dialokasikan segera pada awal layanan, dan semua utas segera dimulai. Ukuran antrian juga tetap. Di runtime, hanya pesan yang sedang diproses.
Sebagai contoh: selain utas utama, layanan tempur cache kami saat ini meluncurkan 100 utas pekerja lainnya, dan ukuran antrian dibatasi hingga tiga ribu pesan. Dalam operasi normal, setiap instance memproses hingga 200 pesan per detik dan menggunakan sekitar 250 MB memori dan sekitar 2-3% dari CPU. Terkadang pada beban puncak, lompatannya menjadi 7-8%. Semuanya bekerja pada beberapa jenis xeon virtual dual-core.
Pekerjaan reguler dari layanan ini menyiratkan pekerjaan serentak dari 3-5 pekerja (dari 100) dengan jumlah pesan dalam antrian 0 (yaitu, mereka langsung memprosesnya). Jika backend mulai melambat, jumlah pekerja yang sibuk meningkat sebanding dengan waktu responnya. Dalam kasus di mana kecelakaan terjadi dan backend naik, maka semua pekerja pertama berakhir, setelah itu antrian pesan mulai menyumbat. Ketika benar-benar tersumbat, kami mulai merespons pelanggan dengan penolakan untuk memproses. Pada saat yang sama, kami tidak mulai memakan sumber daya memori atau CPU, stabil memberikan metrik dan dengan jelas menanggapi pelanggan apa yang terjadi.
Tangkapan layar pertama menunjukkan operasi reguler dari layanan.
Dan yang kedua, kecelakaan terjadi - backend karena alasan tertentu tidak merespons dalam 30 detik. Terlihat bahwa pada awalnya semua pekerja kehabisan, setelah itu antrian pesan mulai menyumbat.
Tes kinerja
Tes sintetis pada mesin saya bekerja (CentOS 7, Core i5, 16Gb RAM) menunjukkan hal berikut.
Bekerja dengan repositori (menulis ke tarantula dan segera membaca catatan ini berukuran 100 byte - simulasi kerja dengan sesi) - 12000 rps.
Hal yang sama, hanya kecepatan diukur bukan antara layanan - titik tarantula, tetapi antara klien dan layanan. Tentu saja, saya harus menulis klien untuk stress testing sendiri. Dalam satu mesin, dimungkinkan untuk mendapatkan 7000 rps. Pada jaringan lokal (dan kami memiliki banyak mesin virtual berbeda yang tidak jelas bagaimana terhubung secara fisik), hasilnya bervariasi, tetapi hingga 5.000 rps untuk satu contoh sangat mungkin. Tuhan tahu kinerja macam apa, tetapi lebih dari sepuluh kali mencakup beban puncak kami. Dan ini hanya jika satu instance dari layanan berjalan, tetapi kami memiliki beberapa dari mereka, dan setiap saat Anda dapat menjalankan sebanyak yang Anda butuhkan. Ketika layanan memblokir kecepatan penyimpanan, dimungkinkan untuk membuat skala tarantula secara horizontal (misalnya, beling berdasarkan ID klien).
Kecerdasan Layanan
Pembaca yang penuh perhatian mungkin sudah mengajukan pertanyaan - apa "kecerdasan" dari layanan ini, yang disebutkan dalam judul. Saya sudah menyebutkan ini secara sepintas, tetapi sekarang saya akan memberi tahu Anda lebih banyak.
Salah satu tugas utama dari layanan ini adalah untuk mengurangi waktu yang dibutuhkan untuk mengeluarkan produk mereka kepada pengguna (daftar akun, kartu, deposito, pinjaman, paket layanan, dll.) Sambil mengurangi beban pada backend (mengurangi jumlah permintaan dalam Oracle besar dan berat) karena caching di tarantula.
Dan dia melakukannya dengan cukup baik. Logika untuk menghangatkan cache klien adalah sebagai berikut:
- pengguna meluncurkan aplikasi seluler;
- Permintaan AppStart yang berisi ID perangkat dikirim ke server depan;
- server depan mengirim pesan dengan ID ini ke layanan cache;
- layanan terlihat di tabel perangkat untuk ID klien untuk perangkat ini;
- jika tidak ada, tidak ada yang terjadi (responsnya bahkan tidak dikirim, server tidak menunggu untuk itu);
- jika ID klien ditemukan, pekerja membuat serangkaian pesan untuk menerima daftar produk pengguna yang segera diproses oleh broker dan didistribusikan ke pekerja dalam mode normal;
- setiap pekerja mengirimkan permintaan untuk tipe data tertentu kepada pengguna, menempatkan status "memperbarui" dalam database (status ini melindungi backend dari mengulangi permintaan yang sama jika mereka datang dari contoh layanan lain);
- setelah menerima data, mereka dicatat di tarantula;
- pengguna masuk ke sistem, dan aplikasi mengirim permintaan untuk menerima produknya, dan server mengirim permintaan ini dalam bentuk pesan ke layanan cache;
- jika data pengguna telah diterima, kami cukup mengirimkannya dari cache;
- jika data sedang dalam proses diterima (status "pemutakhiran"), maka siklus menunggu data dimulai di dalam pekerja (itu sama dengan batas waktu permintaan ke backend);
- segera setelah data diterima (yaitu, status catatan ini (tuple) dalam tabel beralih ke "idle", layanan akan memberikannya kepada klien;
- jika data tidak diterima dalam interval waktu tertentu, kesalahan akan dikembalikan ke klien.
Dengan demikian, dalam praktiknya, kami dapat mengurangi waktu rata-rata untuk menerima produk untuk server depan dari 200 ms hingga 20 ms, yaitu sekitar 10 kali, dan jumlah permintaan ke backend sekitar 4 kali.
Masalahnya
Layanan cache telah bekerja dalam pertempuran selama sekitar dua tahun dan saat ini memenuhi kebutuhan kita.
Tentu saja, masih ada masalah yang belum terselesaikan, terkadang ada masalah. Layanan Java dalam pertempuran belum jatuh. Tarantula jatuh beberapa kali di SIGSEGV, tapi itu beberapa versi lama, dan setelah pembaruan itu tidak terjadi lagi. Selama pengujian stres, replikasi jatuh, pipa pecah terjadi pada master, setelah itu budak jatuh, meskipun master terus bekerja. Diputuskan dengan memulai kembali budak.
Pernah ada semacam kecelakaan di pusat data, dan ternyata sistem operasi (CentOS 7) berhenti melihat hard drive. Sistem file beralih ke mode read-only. Yang paling mengejutkan adalah layanan terus bekerja, karena kami menyimpan semua data dalam memori. Tarantula tidak dapat menulis file .xlog, tidak ada yang mencatat apa pun, tetapi entah bagaimana semuanya bekerja. Tetapi upaya untuk memulai kembali tidak berhasil - tidak ada yang bisa memulai.
Ada satu masalah besar yang belum terpecahkan, dan saya ingin mendengarkan pendapat masyarakat tentang hal ini. Ketika master tarantula macet, layanan java dapat beralih ke slave, yang terus berfungsi sebagai master. Namun, ini hanya terjadi jika master crash dan tidak dapat bekerja.
Misalkan kita memiliki 3 contoh layanan yang bekerja dengan data pada master tarantula. Layanannya sendiri tidak jatuh, replikasi basis data sedang berlangsung, semuanya baik-baik saja. Tapi tiba-tiba kita memiliki jaringan yang berantakan antara node-1 dan node-4, tempat wizard bekerja. Layanan-1 setelah sejumlah upaya gagal memutuskan untuk beralih ke database cadangan dan mulai mengirim permintaan di sana.
Segera setelah ini, budak tarantula mulai menerima permintaan modifikasi data, akibatnya replikasi dari master berantakan, dan kami mendapatkan data yang tidak konsisten. Pada saat yang sama, layanan-2 dan 3 bekerja dengan sempurna dengan master, dan layanan-1 berkomunikasi dengan baik dengan mantan budak. Jelas bahwa dalam kasus ini kita mulai kehilangan sesi klien dan data lainnya, meskipun semuanya bekerja dari sisi teknis. Kami belum memecahkan masalah potensial seperti itu. Untungnya, ini belum terjadi dalam 2 tahun, tetapi situasinya cukup nyata. Sekarang setiap layanan mengetahui jumlah toko, dan kami memiliki peringatan untuk metrik ini, yang akan berfungsi saat beralih dari master ke slave. Dan Anda harus memperbaiki semuanya dengan tangan Anda. Bagaimana Anda memecahkan masalah seperti itu?
Paket
Kami berencana untuk mengatasi masalah yang dijelaskan di atas, membatasi jumlah pekerja yang secara bersamaan sibuk dengan satu jenis permintaan, aman (tanpa kehilangan permintaan saat ini) menghentikan layanan, dan memoles lebih lanjut.
Kesimpulan
Itu, mungkin, itu saja, walaupun saya membahas topik itu agak dangkal, tetapi logika umum dari pekerjaan itu harus jelas. Karena itu, jika memungkinkan, saya siap merespons dalam komentar. Saya jelaskan secara singkat bagaimana satu subsistem pembantu kecil dari server depan bank bekerja untuk melayani klien seluler.
Jika topik tersebut menarik bagi masyarakat, maka saya dapat memberi tahu Anda tentang beberapa solusi kami yang berkontribusi untuk meningkatkan kualitas layanan pelanggan bagi bank.