Blok bangunan aplikasi terdistribusi. Perkiraan kedua

Pengumuman

Rekan-rekan, di pertengahan musim panas saya berencana untuk merilis seri artikel lain tentang desain sistem antrian: “Eksperimen VTrade” - sebuah upaya untuk menulis kerangka kerja untuk sistem perdagangan. Seri ini akan mengkaji teori dan praktik membangun bursa, lelang, dan toko. Di akhir artikel, saya mengundang Anda untuk memilih topik yang paling Anda minati.

Blok bangunan aplikasi terdistribusi. Perkiraan kedua

Ini adalah artikel terakhir dalam seri aplikasi reaktif terdistribusi di Erlang/Elixir. DI DALAM artikel pertama Anda dapat menemukan landasan teoritis arsitektur reaktif. Artikel kedua menggambarkan pola dasar dan mekanisme untuk membangun sistem tersebut.

Hari ini kami akan mengangkat isu-isu pengembangan basis kode dan proyek secara umum.

Organisasi layanan

Dalam kehidupan nyata, saat mengembangkan suatu layanan, Anda sering kali harus menggabungkan beberapa pola interaksi dalam satu pengontrol. Misalnya, layanan pengguna, yang memecahkan masalah pengelolaan profil pengguna proyek, harus merespons permintaan req-resp dan melaporkan pembaruan profil melalui pub-sub. Kasus ini cukup sederhana: di belakang perpesanan terdapat satu pengontrol yang mengimplementasikan logika layanan dan menerbitkan pembaruan.

Situasi menjadi lebih rumit ketika kita perlu menerapkan layanan terdistribusi yang toleran terhadap kesalahan. Bayangkan persyaratan pengguna telah berubah:

  1. sekarang layanan harus memproses permintaan pada 5 node cluster,
  2. dapat melakukan tugas pemrosesan latar belakang,
  3. dan juga dapat mengelola daftar langganan untuk pembaruan profil secara dinamis.

Catatan: Kami tidak mempertimbangkan masalah penyimpanan dan replikasi data yang konsisten. Mari kita asumsikan bahwa masalah ini telah diselesaikan sebelumnya dan sistem telah memiliki lapisan penyimpanan yang andal dan dapat diskalakan, serta penangan memiliki mekanisme untuk berinteraksi dengannya.

Deskripsi formal layanan pengguna menjadi lebih rumit. Dari sudut pandang programmer, perubahan yang terjadi minimal karena penggunaan pesan. Untuk memenuhi persyaratan pertama, kita perlu mengkonfigurasi penyeimbangan pada titik pertukaran req-resp.

Persyaratan untuk memproses tugas latar belakang sering terjadi. Di pengguna, ini bisa berupa pemeriksaan dokumen pengguna, memproses multimedia yang diunduh, atau menyinkronkan data dengan media sosial. jaringan. Tugas-tugas ini perlu didistribusikan dalam cluster dan kemajuan eksekusi dipantau. Oleh karena itu, kami memiliki dua opsi solusi: gunakan templat distribusi tugas dari artikel sebelumnya, atau, jika tidak sesuai, tulis penjadwal tugas khusus yang akan mengelola kumpulan prosesor sesuai kebutuhan.

Poin 3 memerlukan ekstensi template pub-sub. Dan untuk implementasinya, setelah membuat titik pertukaran pub-sub, kita perlu meluncurkan pengontrol titik ini tambahan dalam layanan kita. Dengan demikian, seolah-olah kita memindahkan logika pemrosesan langganan dan berhenti berlangganan dari lapisan pesan ke dalam implementasi pengguna.

Hasilnya, penguraian masalah menunjukkan bahwa untuk memenuhi persyaratan, kita perlu meluncurkan 5 instance layanan pada node yang berbeda dan membuat entitas tambahan - pengontrol pub-sub, yang bertanggung jawab atas langganan.
Untuk menjalankan 5 penangan, Anda tidak perlu mengubah kode layanan. Satu-satunya tindakan tambahan adalah menyiapkan aturan penyeimbangan di titik pertukaran, yang akan kita bahas nanti.
Ada juga kerumitan tambahan: pengontrol pub-sub dan penjadwal tugas khusus harus bekerja dalam satu salinan. Sekali lagi, layanan pesan, sebagai layanan mendasar, harus menyediakan mekanisme untuk memilih pemimpin.

Pemilihan pemimpin

Dalam sistem terdistribusi, pemilihan pemimpin adalah prosedur untuk menunjuk satu proses yang bertanggung jawab untuk menjadwalkan pemrosesan terdistribusi dari beberapa beban.

Dalam sistem yang tidak rentan terhadap sentralisasi, digunakan algoritma universal dan berbasis konsensus, seperti paxos atau raft.
Karena perpesanan adalah perantara dan elemen sentral, ia mengetahui semua pengontrol layanan - calon pemimpin. Pesan dapat menunjuk seorang pemimpin tanpa memilih.

Setelah memulai dan menghubungkan ke titik pertukaran, semua layanan menerima pesan sistem #'$leader'{exchange = ?EXCHANGE, pid = LeaderPid, servers = Servers}. Jika LeaderPid bertepatan dengan pid proses saat ini, ditunjuk sebagai pemimpin, dan daftar Servers mencakup semua node dan parameternya.
Pada saat node cluster baru muncul dan node cluster yang berfungsi terputus, semua pengontrol layanan menerima #'$slave_up'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} и #'$slave_down'{exchange = ?EXCHANGE, pid = SlavePid, options = SlaveOpts} masing.

Dengan cara ini, semua komponen mengetahui semua perubahan, dan cluster dijamin memiliki satu pemimpin pada waktu tertentu.

Mediator

Untuk mengimplementasikan proses pemrosesan terdistribusi yang kompleks, serta dalam masalah mengoptimalkan arsitektur yang ada, akan lebih mudah untuk menggunakan perantara.
Agar tidak mengubah kode layanan dan menyelesaikan, misalnya, masalah pemrosesan tambahan, perutean, atau pencatatan pesan, Anda dapat mengaktifkan penangan proxy sebelum layanan, yang akan melakukan semua pekerjaan tambahan.

Contoh klasik optimasi pub-sub adalah aplikasi terdistribusi dengan inti bisnis yang menghasilkan peristiwa pembaruan, seperti perubahan harga di pasar, dan lapisan akses - server N yang menyediakan API websocket untuk klien web.
Jika Anda memutuskan langsung, maka layanan pelanggan akan terlihat seperti ini:

  • klien menjalin koneksi dengan platform. Di sisi server yang menghentikan lalu lintas, suatu proses diluncurkan untuk melayani koneksi ini.
  • Dalam konteks proses layanan, otorisasi dan berlangganan pembaruan terjadi. Prosesnya memanggil metode berlangganan untuk topik.
  • Setelah suatu peristiwa dihasilkan di kernel, peristiwa itu dikirimkan ke proses yang melayani koneksi.

Bayangkan kita memiliki 50000 pelanggan topik “berita”. Pelanggan didistribusikan secara merata di 5 server. Hasilnya, setiap pembaruan yang tiba di titik pertukaran akan direplikasi 50000 kali: 10000 kali di setiap server, sesuai dengan jumlah pelanggan di dalamnya. Bukan skema yang sangat efektif, bukan?
Untuk memperbaiki situasi ini, mari kita perkenalkan proxy yang memiliki nama yang sama dengan titik pertukaran. Pendaftar nama global harus dapat mengembalikan proses terdekat berdasarkan nama, ini penting.

Mari kita luncurkan proxy ini di server lapisan akses, dan semua proses kita yang melayani api websocket akan berlangganan padanya, dan bukan ke titik pertukaran pub-sub asli di kernel. Proxy berlangganan inti hanya jika ada langganan unik dan mereplikasi pesan masuk ke semua pelanggannya.
Hasilnya, 5 pesan akan dikirim antara kernel dan server akses, bukan 50000.

Perutean dan penyeimbangan

Persyaratan-Resp

Dalam implementasi perpesanan saat ini, terdapat 7 strategi distribusi permintaan:

  • default. Permintaan dikirim ke semua pengontrol.
  • round-robin. Permintaan dihitung dan didistribusikan secara siklis antar pengontrol.
  • consensus. Pengendali yang melayani layanan ini dibagi menjadi pemimpin dan budak. Permintaan dikirim hanya kepada pemimpin.
  • consensus & round-robin. Grup memiliki seorang pemimpin, tetapi permintaan didistribusikan di antara semua anggota.
  • sticky. Fungsi hash dihitung dan ditetapkan ke penangan tertentu. Permintaan berikutnya dengan tanda tangan ini dikirim ke penangan yang sama.
  • sticky-fun. Saat menginisialisasi titik pertukaran, fungsi perhitungan hash untuk sticky menyeimbangkan.
  • fun. Mirip dengan stick-fun, hanya Anda yang dapat mengalihkan, menolak, atau memprosesnya terlebih dahulu.

Strategi distribusi diatur ketika titik pertukaran diinisialisasi.

Selain penyeimbangan, perpesanan memungkinkan Anda menandai entitas. Mari kita lihat jenis-jenis tag dalam sistem:

  • Label koneksi. Memungkinkan Anda memahami melalui hubungan mana peristiwa itu terjadi. Digunakan ketika proses pengontrol terhubung ke titik pertukaran yang sama, tetapi dengan kunci perutean yang berbeda.
  • Label layanan. Memungkinkan Anda menggabungkan penangan ke dalam grup untuk satu layanan dan memperluas kemampuan perutean dan penyeimbangan. Untuk pola req-resp, peruteannya linier. Kami mengirimkan permintaan ke titik pertukaran, lalu meneruskannya ke layanan. Tetapi jika kita perlu membagi penangan menjadi kelompok-kelompok logis, maka pemisahan dilakukan dengan menggunakan tag. Saat menentukan tag, permintaan akan dikirim ke grup pengontrol tertentu.
  • Tag permintaan. Memungkinkan Anda membedakan jawaban. Karena sistem kita tidak sinkron, untuk memproses respons layanan, kita harus dapat menentukan RequestTag saat mengirim permintaan. Dari situ kita akan bisa memahami jawaban atas permintaan yang datang kepada kita.

Pub-sub

Untuk pub-sub semuanya sedikit lebih sederhana. Kami memiliki titik pertukaran tempat pesan dipublikasikan. Titik pertukaran mendistribusikan pesan di antara pelanggan yang telah berlangganan kunci perutean yang mereka perlukan (kita dapat mengatakan bahwa ini serupa dengan topik).

Skalabilitas dan toleransi kesalahan

Skalabilitas sistem secara keseluruhan bergantung pada tingkat skalabilitas lapisan dan komponen sistem:

  • Layanan diskalakan dengan menambahkan node tambahan ke klaster dengan penangan untuk layanan ini. Selama operasi uji coba, Anda dapat memilih kebijakan penyeimbangan yang optimal.
  • Layanan pesan itu sendiri dalam cluster terpisah umumnya diskalakan dengan memindahkan titik pertukaran yang dimuat secara khusus ke node cluster yang terpisah, atau dengan menambahkan proses proksi ke area cluster yang dimuat secara khusus.
  • Skalabilitas seluruh sistem sebagai karakteristik bergantung pada fleksibilitas arsitektur dan kemampuan untuk menggabungkan cluster individu menjadi entitas logis yang sama.

Keberhasilan suatu proyek sering kali bergantung pada kesederhanaan dan kecepatan penskalaan. Perpesanan dalam versi saat ini berkembang seiring dengan perkembangan aplikasi. Bahkan jika kita kekurangan kelompok yang terdiri dari 50-60 mesin, kita dapat menggunakan federasi. Sayangnya, topik federasi berada di luar cakupan artikel ini.

Reservasi

Saat menganalisis penyeimbangan beban, kita telah membahas redundansi pengontrol layanan. Namun, pesan juga harus dicadangkan. Jika terjadi kerusakan pada node atau mesin, pesan akan pulih secara otomatis, dan dalam waktu sesingkat mungkin.

Dalam proyek saya, saya menggunakan node tambahan yang mengambil beban jika terjatuh. Erlang memiliki implementasi mode terdistribusi standar untuk aplikasi OTP. Mode terdistribusi melakukan pemulihan jika terjadi kegagalan dengan meluncurkan aplikasi yang gagal pada node lain yang diluncurkan sebelumnya. Prosesnya transparan; setelah kegagalan, aplikasi secara otomatis berpindah ke node failover. Anda dapat membaca lebih lanjut tentang fungsi ini di sini.

Performa

Mari kita coba setidaknya membandingkan secara kasar kinerja Rabbitmq dan pesan khusus kita.
saya menemukan hasil resmi pengujian Rabbitmq dari tim openstack.

Dalam paragraf 6.14.1.2.1.2.2. Dokumen asli menunjukkan hasil RPC CAST:
Blok bangunan aplikasi terdistribusi. Perkiraan kedua

Kami tidak akan membuat pengaturan tambahan apa pun pada kernel OS atau erlang VM terlebih dahulu. Kondisi untuk pengujian:

  • erl memilih: +A1 +sbtu.
  • Pengujian dalam satu node erlang dijalankan pada laptop dengan i7 lama dalam versi seluler.
  • Uji cluster dilakukan pada server dengan jaringan 10G.
  • Kode berjalan di kontainer buruh pelabuhan. Jaringan dalam mode NAT.

Kode tes:

req_resp_bench(_) ->
  W = perftest:comprehensive(10000,
    fun() ->
      messaging:request(?EXCHANGE, default, ping, self()),
      receive
        #'$msg'{message = pong} -> ok
      after 5000 ->
        throw(timeout)
      end
    end
  ),
  true = lists:any(fun(E) -> E >= 30000 end, W),
  ok.

Skenario 1: Pengujian dijalankan pada laptop dengan versi seluler i7 lama. Pengujian, pengiriman pesan, dan layanan dijalankan pada satu node dalam satu container Docker:

Sequential 10000 cycles in ~0 seconds (26987 cycles/s)
Sequential 20000 cycles in ~1 seconds (26915 cycles/s)
Sequential 100000 cycles in ~4 seconds (26957 cycles/s)
Parallel 2 100000 cycles in ~2 seconds (44240 cycles/s)
Parallel 4 100000 cycles in ~2 seconds (53459 cycles/s)
Parallel 10 100000 cycles in ~2 seconds (52283 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (49317 cycles/s)

skenario 2: 3 node berjalan pada mesin berbeda di bawah buruh pelabuhan (NAT).

Sequential 10000 cycles in ~1 seconds (8684 cycles/s)
Sequential 20000 cycles in ~2 seconds (8424 cycles/s)
Sequential 100000 cycles in ~12 seconds (8655 cycles/s)
Parallel 2 100000 cycles in ~7 seconds (15160 cycles/s)
Parallel 4 100000 cycles in ~5 seconds (19133 cycles/s)
Parallel 10 100000 cycles in ~4 seconds (24399 cycles/s)
Parallel 100 100000 cycles in ~3 seconds (34517 cycles/s)

Dalam semua kasus, penggunaan CPU tidak melebihi 250%

Hasil

Saya berharap siklus ini tidak tampak seperti sebuah pemikiran yang sia-sia dan pengalaman saya akan memberikan manfaat nyata bagi para peneliti sistem terdistribusi dan praktisi yang berada pada tahap awal membangun arsitektur terdistribusi untuk sistem bisnis mereka dan sedang mempelajari Erlang/Elixir dengan penuh minat. , tapi ragu apakah itu layak...

foto @chuttersnap

Hanya pengguna terdaftar yang dapat berpartisipasi dalam survei. Masuk, silakan.

Topik apa yang harus saya bahas lebih detail sebagai bagian dari seri Eksperimen VTrade?

  • Teori: Pasar, pesanan dan waktunya: DAY, GTD, GTC, IOC, FOK, MOO, MOC, LOO, LOC

  • Buku pesanan. Teori dan praktek penerapan buku dengan pengelompokan

  • Visualisasi perdagangan: Kutu, batang, resolusi. Cara menyimpan dan cara merekatkannya

  • kantor belakang. Perencanaan dan pengembangan. Pemantauan karyawan dan investigasi insiden

  • API. Mari kita cari tahu antarmuka apa yang dibutuhkan dan bagaimana mengimplementasikannya

  • Penyimpanan informasi: PostgreSQL, Timescale, Tarantool dalam sistem perdagangan

  • Reaktivitas dalam sistem perdagangan

  • Lainnya. Saya akan menulis di komentar

6 pengguna memilih. 4 pengguna abstain.

Sumber: www.habr.com

Tambah komentar