Di Mail.ru Group kami mempunyai Tarantool - ini adalah pelayan aplikasi di Lua, yang juga berfungsi sebagai pangkalan data (atau sebaliknya?). Ia pantas dan sejuk, tetapi keupayaan satu pelayan masih tidak terhad. Penskalaan menegak juga bukan ubat penawar, jadi Tarantool mempunyai alat untuk penskalaan mendatar - modul vshard
Berita baik: kami telah mengumpul beberapa gambar besar (cth
Apa sebenarnya masalahnya?
Kami ada tarantula, kami ada vshard - apa lagi yang anda mahukan?
Pertama, ini soal kemudahan. Konfigurasi vshard dikonfigurasikan melalui jadual Lua. Untuk sistem pengedaran berbilang proses Tarantool berfungsi dengan betul, konfigurasi mestilah sama di semua tempat. Tiada siapa yang mahu melakukan ini secara manual. Oleh itu, semua jenis skrip, Ansible dan sistem penggunaan digunakan.
Kartrij sendiri menguruskan konfigurasi vshard, ia melakukan ini berdasarkannya konfigurasi teragih sendiri. Ia pada asasnya adalah fail YAML yang mudah, salinannya disimpan dalam setiap contoh Tarantool. Penyederhanaan adalah bahawa rangka kerja itu sendiri memantau konfigurasinya dan memastikan bahawa ia adalah sama di mana-mana.
Kedua, ia sekali lagi soal kemudahan. Konfigurasi vshard tidak ada kaitan dengan pembangunan logik perniagaan dan hanya mengalihkan perhatian pengaturcara daripada kerjanya. Apabila kita membincangkan seni bina projek, kita paling kerap bercakap tentang komponen individu dan interaksinya. Masih terlalu awal untuk memikirkan tentang melancarkan kluster ke 3 pusat data.
Kami menyelesaikan masalah ini berulang kali, dan pada satu ketika kami berjaya membangunkan pendekatan yang memudahkan kerja dengan aplikasi sepanjang keseluruhan kitaran hayatnya: penciptaan, pembangunan, ujian, CI/CD, penyelenggaraan.
Kartrij memperkenalkan konsep peranan untuk setiap proses Tarantool. Peranan ialah konsep yang membolehkan pembangun menumpukan pada menulis kod. Semua peranan yang tersedia dalam projek boleh dijalankan pada satu contoh Tarantool, dan ini akan mencukupi untuk ujian.
Ciri utama Kartrij Tarantool:
- orkestrasi kelompok automatik;
- mengembangkan kefungsian aplikasi menggunakan peranan baharu;
- templat aplikasi untuk pembangunan dan penggunaan;
- sharding automatik terbina dalam;
- penyepaduan dengan rangka kerja ujian Luatest;
- pengurusan kluster menggunakan WebUI dan API;
- alat pembungkusan dan penggunaan.
Hai dunia!
Saya tidak sabar untuk menunjukkan rangka kerja itu sendiri, jadi kami akan meninggalkan cerita tentang seni bina untuk kemudian dan mulakan dengan sesuatu yang mudah. Jika kita menganggap bahawa Tarantool sendiri sudah dipasang, maka yang tinggal hanyalah lakukan
$ tarantoolctl rocks install cartridge-cli
$ export PATH=$PWD/.rocks/bin/:$PATH
Kedua-dua arahan ini akan memasang utiliti baris arahan dan membolehkan anda membuat aplikasi pertama anda daripada templat:
$ cartridge create --name myapp
Dan inilah yang kami dapat:
myapp/
├── .git/
├── .gitignore
├── app/roles/custom.lua
├── deps.sh
├── init.lua
├── myapp-scm-1.rockspec
├── test
│ ├── helper
│ │ ├── integration.lua
│ │ └── unit.lua
│ ├── helper.lua
│ ├── integration/api_test.lua
│ └── unit/sample_test.lua
└── tmp/
Ini adalah repositori git dengan "Hello, World!" siap sedia. permohonan. Mari cuba jalankannya dengan segera, setelah memasang kebergantungan sebelum ini (termasuk rangka kerja itu sendiri):
$ tarantoolctl rocks make
$ ./init.lua --http-port 8080
Jadi, kami mempunyai satu nod yang berjalan untuk aplikasi sharded masa hadapan. Orang awam yang ingin tahu boleh segera membuka antara muka web, mengkonfigurasi kelompok satu nod dengan tetikus dan menikmati hasilnya, tetapi masih terlalu awal untuk bergembira. Setakat ini, aplikasi itu tidak boleh melakukan apa-apa yang berguna, jadi saya akan memberitahu anda tentang penempatan kemudian, tetapi kini tiba masanya untuk menulis kod.
Pembangunan Aplikasi
Bayangkan, kami sedang mereka bentuk projek yang mesti menerima data, simpan dan bina laporan sekali sehari.
Kami mula melukis gambar rajah dan meletakkan tiga komponen di atasnya: pintu masuk, penyimpanan dan penjadual. Kami sedang mengusahakan seni bina dengan lebih lanjut. Oleh kerana kami menggunakan vshard sebagai storan, kami menambah vshard-router dan vshard-storage pada skema. Gerbang atau penjadual tidak akan mengakses storan secara langsung; untuk itulah penghala, untuk itulah ia dicipta.
Gambar rajah ini masih tidak mewakili apa yang akan kami bina dalam projek kerana komponen kelihatan abstrak. Kita masih perlu melihat bagaimana ini akan ditayangkan ke Tarantool sebenar - mari kumpulkan komponen kita mengikut proses.
Tidak ada gunanya mengekalkan vshard-router dan gateway pada kejadian yang berasingan. Mengapa kita perlu melayari rangkaian sekali lagi jika ini sudah menjadi tanggungjawab penghala? Mereka mesti dijalankan dalam proses yang sama. Iaitu, kedua-dua gerbang dan vshard.router.cfg dimulakan dalam satu proses dan biarkan mereka berinteraksi secara setempat.
Pada peringkat reka bentuk, adalah mudah untuk bekerja dengan tiga komponen, tetapi saya, sebagai pemaju, semasa menulis kod, tidak mahu berfikir tentang melancarkan tiga contoh Tarnatool. Saya perlu menjalankan ujian dan menyemak sama ada saya menulis get laluan dengan betul. Atau mungkin saya ingin menunjukkan ciri kepada rakan sekerja saya. Mengapa saya perlu melalui kerumitan menggunakan tiga salinan? Ini adalah bagaimana konsep peranan dilahirkan. Peranan ialah modul luash biasa yang kitaran hayatnya diuruskan oleh Cartridge. Dalam contoh ini terdapat empat daripadanya - pintu masuk, penghala, penyimpanan, penjadual. Mungkin ada lagi dalam projek lain. Semua peranan boleh dijalankan dalam satu proses, dan ini sudah memadai.
Dan apabila ia berkaitan dengan penggunaan kepada pementasan atau pengeluaran, maka kami akan menetapkan setiap proses Tarantool set peranannya sendiri bergantung pada keupayaan perkakasan:
Pengurusan topologi
Maklumat tentang di mana peranan yang dijalankan mesti disimpan di suatu tempat. Dan "suatu tempat" ini adalah konfigurasi yang diedarkan, yang telah saya nyatakan di atas. Perkara yang paling penting mengenainya ialah topologi kluster. Berikut ialah 3 kumpulan replikasi 5 proses Tarantool:
Kami tidak mahu kehilangan data, jadi kami merawat maklumat tentang proses yang sedang berjalan dengan berhati-hati. Kartrij menjejaki konfigurasi menggunakan komit dua fasa. Sebaik sahaja kami ingin mengemas kini konfigurasi, ia mula-mula menyemak bahawa semua kejadian tersedia dan bersedia untuk menerima konfigurasi baharu. Selepas ini, fasa kedua menggunakan konfigurasi. Oleh itu, walaupun satu salinan ternyata tidak tersedia buat sementara waktu, tiada perkara buruk akan berlaku. Konfigurasi tidak akan digunakan dan anda akan melihat ralat terlebih dahulu.
Juga dalam bahagian topologi, parameter penting seperti ketua setiap kumpulan replikasi ditunjukkan. Biasanya ini adalah salinan yang sedang dirakam. Selebihnya paling kerap dibaca sahaja, walaupun mungkin terdapat pengecualian. Kadang-kadang pembangun yang berani tidak takut konflik dan boleh menulis data kepada beberapa replika secara selari, tetapi terdapat beberapa operasi yang, tidak kira apa, tidak boleh dilakukan dua kali. Untuk ini ada tanda seorang pemimpin.
Kehidupan peranan
Untuk peranan abstrak wujud dalam seni bina sedemikian, rangka kerja mesti menguruskannya entah bagaimana. Sememangnya, kawalan berlaku tanpa memulakan semula proses Tarantool. Terdapat 4 panggilan balik untuk mengurus peranan. Kartrij sendiri akan memanggilnya bergantung pada apa yang tertulis dalam konfigurasi yang diedarkannya, dengan itu menggunakan konfigurasi pada peranan tertentu.
function init()
function validate_config()
function apply_config()
function stop()
Setiap peranan mempunyai fungsi init
. Ia dipanggil sekali sama ada apabila peranan didayakan atau apabila Tarantool dimulakan semula. Ia adalah mudah di sana, sebagai contoh, untuk memulakan box.space.create, atau penjadual boleh melancarkan beberapa gentian latar belakang yang akan melaksanakan kerja pada selang masa tertentu.
Satu fungsi init
mungkin tidak cukup. Kartrij membenarkan peranan mengambil kesempatan daripada konfigurasi teragih yang digunakan untuk menyimpan topologi. Kami boleh mengisytiharkan bahagian baharu dalam konfigurasi yang sama dan menyimpan serpihan konfigurasi perniagaan di dalamnya. Dalam contoh saya, ini boleh menjadi skema data atau tetapan jadual untuk peranan penjadual.
Panggilan kluster validate_config
и apply_config
setiap kali konfigurasi yang diedarkan berubah. Apabila konfigurasi digunakan oleh komit dua fasa, kluster menyemak bahawa setiap peranan bersedia untuk menerima konfigurasi baharu ini dan, jika perlu, melaporkan ralat kepada pengguna. Apabila semua orang bersetuju bahawa konfigurasi adalah normal, maka apply_config
.
Juga peranan mempunyai kaedah stop
, yang diperlukan untuk membersihkan output peranan. Jika kita mengatakan bahawa penjadual tidak lagi diperlukan pada pelayan ini, ia boleh menghentikan gentian yang ia bermula init
.
Peranan boleh berinteraksi antara satu sama lain. Kami biasa menulis panggilan fungsi dalam Lua, tetapi mungkin berlaku proses tertentu tidak mempunyai peranan yang kami perlukan. Untuk memudahkan panggilan melalui rangkaian, kami menggunakan modul tambahan rpc (panggilan prosedur jauh), yang dibina berdasarkan kotak bersih standard yang dibina ke dalam Tarantool. Ini boleh berguna jika, sebagai contoh, gerbang anda ingin meminta penjadual secara langsung untuk melakukan kerja sekarang, dan bukannya menunggu sehari.
Satu lagi perkara penting ialah memastikan toleransi kesalahan. Kartrij menggunakan protokol SWIM untuk memantau kesihatan
Berdasarkan protokol ini, Kartrij mengatur pemprosesan kegagalan automatik. Setiap proses memantau persekitarannya, dan jika pemimpin tiba-tiba berhenti bertindak balas, replika boleh mengambil alih peranannya, dan Cartridge mengkonfigurasi peranan berjalan dengan sewajarnya.
Anda perlu berhati-hati di sini, kerana bertukar-tukar yang kerap boleh menyebabkan konflik data semasa replikasi. Sudah tentu, anda tidak seharusnya mendayakan failover automatik secara rawak. Kita mesti faham dengan jelas apa yang berlaku dan pastikan replikasi tidak akan putus selepas pemimpin dipulihkan dan mahkota dikembalikan kepadanya.
Daripada semua ini, anda mungkin mendapat perasaan bahawa peranan adalah serupa dengan perkhidmatan mikro. Dalam erti kata lain, mereka hanya itu, hanya sebagai modul dalam proses Tarantool. Tetapi terdapat juga beberapa perbezaan asas. Pertama, semua peranan projek mesti hidup dalam asas kod yang sama. Dan semua proses Tarantool harus dilancarkan dari pangkalan kod yang sama, supaya tidak ada kejutan seperti itu apabila kami cuba memulakan penjadual, tetapi ia tidak wujud. Selain itu, anda tidak seharusnya membenarkan perbezaan dalam versi kod, kerana kelakuan sistem dalam situasi sedemikian sangat sukar untuk diramal dan nyahpepijat.
Tidak seperti Docker, kita tidak boleh hanya mengambil peranan "imej", membawanya ke mesin lain dan menjalankannya di sana. Peranan kami tidak terpencil seperti bekas Docker. Selain itu, kita tidak boleh menjalankan dua peranan yang sama pada satu contoh. Peranan sama ada wujud atau tidak; dalam erti kata lain, ia adalah tunggal. Dan ketiga, peranan mestilah sama dalam keseluruhan kumpulan replikasi, kerana jika tidak, ia akan menjadi tidak masuk akal - data adalah sama, tetapi konfigurasinya berbeza.
Alat penyebaran
Saya berjanji untuk menunjukkan cara Cartridge membantu menggunakan aplikasi. Untuk menjadikan hidup lebih mudah bagi orang lain, rangka kerja pakej RPM:
$ cartridge pack rpm myapp -- упакует для нас ./myapp-0.1.0-1.rpm
$ sudo yum install ./myapp-0.1.0-1.rpm
Pakej yang dipasang mengandungi hampir semua yang anda perlukan: kedua-dua aplikasi dan kebergantungan yang dipasang. Tarantool juga akan tiba di pelayan sebagai kebergantungan pakej RPM, dan perkhidmatan kami sedia untuk dilancarkan. Ini dilakukan melalui systemd, tetapi pertama-tama anda perlu menulis sedikit konfigurasi. Sekurang-kurangnya, nyatakan URI setiap proses. Tiga sudah memadai sebagai contoh.
$ sudo tee /etc/tarantool/conf.d/demo.yml <<CONFIG
myapp.router: {"advertise_uri": "localhost:3301", "http_port": 8080}
myapp.storage_A: {"advertise_uri": "localhost:3302", "http_enabled": False}
myapp.storage_B: {"advertise_uri": "localhost:3303", "http_enabled": False}
CONFIG
Terdapat nuansa menarik di sini. Daripada menyatakan hanya port protokol binari, kami menentukan keseluruhan alamat awam proses termasuk nama hos. Ini adalah perlu supaya nod kluster tahu cara menyambung antara satu sama lain. Adalah idea yang tidak baik untuk menggunakan 0.0.0.0 sebagai alamat advertise_uri; ia mestilah alamat IP luaran, bukan ikatan soket. Tanpanya, tiada apa yang akan berfungsi, jadi Cartridge tidak akan membenarkan anda melancarkan nod dengan advertise_uri yang salah.
Sekarang bahawa konfigurasi sudah sedia, anda boleh memulakan proses. Oleh kerana unit sistem biasa tidak membenarkan lebih daripada satu proses dimulakan, aplikasi pada Kartrij dipasang oleh yang dipanggil. unit instantiated yang berfungsi seperti ini:
$ sudo systemctl start myapp@router
$ sudo systemctl start myapp@storage_A
$ sudo systemctl start myapp@storage_B
Dalam konfigurasi, kami menentukan port HTTP di mana Kartrij menyediakan antara muka web - 8080. Mari kita pergi ke sana dan lihat:
Kami melihat bahawa walaupun proses sedang berjalan, mereka belum dikonfigurasikan. Kartrij belum tahu siapa yang harus meniru dengan siapa dan tidak boleh membuat keputusan sendiri, jadi ia sedang menunggu tindakan kami. Tetapi kami tidak mempunyai banyak pilihan: hayat kluster baharu bermula dengan konfigurasi nod pertama. Kemudian kami akan menambah yang lain pada kluster, memberikan mereka peranan, dan pada ketika ini penempatan boleh dianggap berjaya diselesaikan.
Mari tuangkan segelas minuman kegemaran anda dan berehat selepas seminggu bekerja yang panjang. Aplikasi itu boleh digunakan.
Keputusan
Apakah keputusannya? Cubalah, gunakannya, tinggalkan maklum balas, buat tiket di Github.
rujukan
[1]
Sumber: www.habr.com