Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

U Mail.ru Group imamo Tarantool - ovo je poslužitelj aplikacija u Lua, koji također služi kao baza podataka (ili obrnuto?). Brz je i cool, ali mogućnosti jednog poslužitelja još uvijek nisu neograničene. Vertikalno skaliranje također nije lijek, pa Tarantool ima alate za horizontalno skaliranje - modul vshard [1]. Omogućuje vam dijeljenje podataka na nekoliko poslužitelja, ali morate petljati s njim da biste ga postavili i priložili poslovnu logiku.

Dobre vijesti: prikupili smo neke velike snimke (npr [2], [3]) i stvorio još jedan okvir koji će značajno pojednostaviti rješenje ovog problema.

Tarantool patrona je novi okvir za razvoj složenih distribuiranih sustava. Omogućuje vam da se usredotočite na pisanje poslovne logike umjesto na rješavanje infrastrukturnih problema. U nastavku ću vam reći kako ovaj okvir funkcionira i kako pisati distribuirane usluge pomoću njega.

Što je točno problem?

Imamo tarantulu, imamo vshard - što više možete poželjeti?

Prvo, to je stvar pogodnosti. Konfiguracija vshard konfigurira se putem Lua tablica. Da bi distribuirani sustav više Tarantool procesa ispravno radio, konfiguracija mora biti svugdje ista. Nitko to ne želi raditi ručno. Stoga se koriste sve vrste skripti, Ansible i sustava za implementaciju.

Sam uložak upravlja konfiguracijom vsharda, čini to na temelju svojeg vlastitu distribuiranu konfiguraciju. To je u biti jednostavna YAML datoteka, čija je kopija pohranjena u svakoj instanci Tarantoola. Pojednostavljenje je da sam okvir nadzire svoju konfiguraciju i osigurava da je posvuda isti.

Drugo, opet je stvar pogodnosti. Konfiguracija vshard nema nikakve veze s razvojem poslovne logike i samo odvlači programera od njegovog rada. Kada govorimo o arhitekturi projekta, najčešće govorimo o pojedinačnim komponentama i njihovoj interakciji. Prerano je razmišljati o uvođenju klastera u 3 podatkovna centra.

Te smo probleme uvijek iznova rješavali iu nekom trenutku uspjeli razviti pristup koji je pojednostavio rad s aplikacijom kroz cijeli životni ciklus: kreiranje, razvoj, testiranje, CI/CD, održavanje.

Cartridge uvodi koncept uloge za svaki Tarantool proces. Uloge su koncept koji programeru omogućuje da se usredotoči na pisanje koda. Sve uloge dostupne u projektu mogu se pokrenuti na jednoj instanci Tarantoola, a to će biti dovoljno za testove.

Ključne značajke Tarantool kasete:

  • automatizirana orkestracija klastera;
  • proširenje funkcionalnosti aplikacije korištenjem novih uloga;
  • predložak aplikacije za razvoj i implementaciju;
  • ugrađeno automatsko dijeljenje;
  • integracija s okvirom za testiranje Luatest;
  • upravljanje klasterom pomoću WebUI i API-ja;
  • alati za pakiranje i postavljanje.

Pozdrav svijete!

Jedva čekam pokazati sam framework, pa ćemo priču o arhitekturi ostaviti za kasnije i krenuti s nečim jednostavnim. Ako pretpostavimo da je sam Tarantool već instaliran, onda sve što preostaje je učiniti

$ tarantoolctl rocks install cartridge-cli
$ export PATH=$PWD/.rocks/bin/:$PATH

Ove dvije naredbe instalirat će pomoćne programe naredbenog retka i omogućiti vam da izradite svoju prvu aplikaciju iz predloška:

$ cartridge create --name myapp

I evo što dobivamo:

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/

Ovo je git repozitorij sa gotovim "Hello, World!" primjena. Pokušajmo ga odmah pokrenuti, nakon što smo prethodno instalirali ovisnosti (uključujući sam okvir):

$ tarantoolctl rocks make
$ ./init.lua --http-port 8080

Dakle, imamo jedan čvor koji radi za buduću dijeljenu aplikaciju. Radoznali laik može odmah otvoriti web sučelje, mišem konfigurirati klaster od jednog čvora i uživati ​​u rezultatu, ali prerano je radovati se. Za sada aplikacija ne može učiniti ništa korisno, pa ću vam kasnije reći o implementaciji, ali sada je vrijeme da napišete kod.

Razvoj aplikacija

Zamislite, mi dizajniramo projekt koji mora primati podatke, spremati ih i jednom dnevno napraviti izvještaj.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Počinjemo crtati dijagram i na njega postavljamo tri komponente: gateway, storage i scheduler. Nadalje radimo na arhitekturi. Budući da koristimo vshard kao pohranu, shemi dodajemo vshard-router i vshard-storage. Ni pristupnik ni planer neće izravno pristupiti pohrani; za to je usmjerivač, za to je stvoren.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Ovaj dijagram još uvijek ne predstavlja točno ono što ćemo graditi u projektu jer komponente izgledaju apstraktno. Još uvijek trebamo vidjeti kako će se to projicirati na pravi Tarantool - grupirajmo naše komponente po procesu.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Nema smisla držati vshard-router i gateway na odvojenim instancama. Zašto moramo još jednom surfati mrežom ako je to već odgovornost rutera? Moraju se izvoditi unutar istog procesa. To jest, i gateway i vshard.router.cfg se inicijaliziraju u jednom procesu i puštaju ih da međusobno djeluju lokalno.

U fazi dizajna bilo je zgodno raditi s tri komponente, ali ja, kao programer, dok pišem kod, ne želim razmišljati o pokretanju tri instance Tarnatoola. Moram pokrenuti testove i provjeriti jesam li ispravno napisao gateway. Ili možda želim demonstrirati značajku svojim kolegama. Zašto bih se mučio s postavljanjem tri kopije? Tako je nastao koncept uloga. Uloga je uobičajeni luash modul čijim životnim ciklusom upravlja Cartridge. U ovom primjeru postoje ih četiri - gateway, router, storage, scheduler. Možda će ih biti više u nekom drugom projektu. Sve uloge mogu se pokrenuti u jednom procesu i ovo će biti dovoljno.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

A kada je u pitanju implementacija u staging ili proizvodnju, tada ćemo svakom Tarantool procesu dodijeliti vlastiti skup uloga ovisno o hardverskim mogućnostima:

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Upravljanje topologijom

Informacije o tome gdje se koje uloge izvode moraju biti negdje pohranjene. A ovo "negdje" je distribuirana konfiguracija, koju sam već spomenuo gore. Najvažnija stvar kod njega je topologija klastera. Ovdje su 3 grupe replikacije od 5 Tarantool procesa:

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Ne želimo izgubiti podatke, stoga s informacijama o pokrenutim procesima postupamo pažljivo. Spremnik prati konfiguraciju pomoću dvofaznog preuzimanja. Nakon što želimo ažurirati konfiguraciju, prvo provjerava jesu li sve instance dostupne i spremne prihvatiti novu konfiguraciju. Nakon toga, druga faza primjenjuje konfiguraciju. Dakle, čak i ako se ispostavi da je jedan primjerak privremeno nedostupan, neće se dogoditi ništa loše. Konfiguracija se jednostavno neće primijeniti i unaprijed ćete vidjeti pogrešku.

Također u odjeljku o topologiji naznačen je tako važan parametar kao voditelj svake replikacijske grupe. Obično je ovo kopija koja se snima. Ostali su najčešće samo za čitanje, iako može biti iznimaka. Ponekad se hrabri programeri ne boje sukoba i mogu pisati podatke u nekoliko replika paralelno, ali postoje neke operacije koje se, bez obzira na sve, ne bi trebale izvoditi dvaput. Za to postoji znak vođe.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Život uloga

Da bi apstraktna uloga postojala u takvoj arhitekturi, okvir mora njima nekako upravljati. Naravno, kontrola se odvija bez ponovnog pokretanja Tarantool procesa. Postoje 4 povratna poziva za upravljanje ulogama. Cartridge će ih sam pozvati ovisno o tome što je zapisano u njegovoj distribuiranoj konfiguraciji, čime se konfiguracija primjenjuje na određene uloge.

function init()
function validate_config()
function apply_config()
function stop()

Svaka uloga ima funkciju init. Poziva se jednom ili kada je uloga omogućena ili kada se Tarantool ponovno pokrene. Tamo je zgodno, na primjer, inicijalizirati box.space.create ili planer može pokrenuti neko pozadinsko vlakno koje će raditi u određenim vremenskim intervalima.

Jedna funkcija init možda neće biti dovoljno. Spremnik omogućuje ulogama da iskoriste prednost distribuirane konfiguracije koju koristi za pohranjivanje topologije. Možemo deklarirati novi odjeljak u istoj konfiguraciji i u njega pohraniti fragment poslovne konfiguracije. U mom primjeru, to bi mogla biti shema podataka ili postavke rasporeda za ulogu planera.

Klasterski pozivi validate_config и apply_config svaki put kada se promijeni distribuirana konfiguracija. Kada se konfiguracija primijeni dvofaznim preuzimanjem, klaster provjerava je li svaka uloga spremna prihvatiti ovu novu konfiguraciju i, ako je potrebno, prijavljuje pogrešku korisniku. Kada se svi slože da je konfiguracija normalna, onda je apply_config.

I uloge imaju metodu stop, koji je potreban za čišćenje izlaza uloge. Ako kažemo da planer više nije potreban na ovom poslužitelju, on može zaustaviti ta vlakna s kojima je počeo init.

Uloge mogu međusobno komunicirati. Navikli smo pisati pozive funkcija u Lui, ali može se dogoditi da određeni proces nema ulogu koju trebamo. Kako bismo olakšali pozive preko mreže, koristimo pomoćni modul rpc (remote procedure call), koji je izgrađen na temelju standardnog netboxa ugrađenog u Tarantool. To može biti korisno ako, na primjer, vaš pristupnik želi izravno zatražiti od planera da obavi posao odmah, umjesto da čeka dan.

Još jedna važna točka je osiguranje tolerancije na pogreške. Uložak koristi SWIM protokol za praćenje zdravlja [4]. Ukratko, procesi međusobno razmjenjuju "glasine" preko UDP-a - svaki proces svojim susjedima govori najnovije vijesti, a oni odgovaraju. Ako iznenada ne dođe do odgovora, Tarantool počinje sumnjati da nešto nije u redu, a nakon nekog vremena izgovara smrt i počinje svima govoriti tu vijest.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Na temelju ovog protokola, Cartridge organizira automatsku obradu kvarova. Svaki proces nadzire svoje okruženje, a ako voditelj iznenada prestane odgovarati, replika može preuzeti njegovu ulogu, a Cartridge u skladu s tim konfigurira tekuće uloge.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Ovdje morate biti oprezni jer često prebacivanje naprijed-natrag može dovesti do sukoba podataka tijekom replikacije. Naravno, ne biste trebali nasumično omogućiti automatsko prebacivanje. Moramo jasno razumjeti što se događa i biti sigurni da se replikacija neće prekinuti nakon što se vođa obnovi i kruna mu se vrati.

Iz svega ovoga možete dobiti osjećaj da su uloge slične mikroservisima. U određenom smislu, oni su upravo to, samo kao moduli unutar Tarantool procesa. Ali postoji i niz temeljnih razlika. Prvo, sve projektne uloge moraju živjeti u istoj bazi koda. I svi Tarantool procesi bi trebali biti pokrenuti iz iste baze koda, kako ne bi bilo iznenađenja poput onih kada pokušamo inicijalizirati planer, ali on jednostavno ne postoji. Također, ne biste trebali dopustiti razlike u verzijama koda, jer je ponašanje sustava u takvoj situaciji vrlo teško predvidjeti i otkloniti pogreške.

Za razliku od Dockera, ne možemo samo uzeti "sliku" uloge, odnijeti je na drugi stroj i pokrenuti tamo. Naše uloge nisu izolirane kao Docker spremnici. Također, ne možemo pokrenuti dvije identične uloge na jednoj instanci. Uloga ili postoji ili ne; u određenom smislu, to je samac. I treće, uloge moraju biti iste unutar cijele replikacijske grupe, jer bi inače bilo apsurdno - podaci su isti, ali je drugačija konfiguracija.

Alati za implementaciju

Obećao sam pokazati kako Cartridge pomaže u implementaciji aplikacija. Kako bi drugima olakšao život, framework sadrži RPM pakete:

$ cartridge pack rpm myapp -- упакует для нас ./myapp-0.1.0-1.rpm
$ sudo yum install ./myapp-0.1.0-1.rpm

Instalirani paket sadrži gotovo sve što vam je potrebno: i aplikaciju i instalirane ovisnosti. Tarantool će također stići na poslužitelj kao ovisnost RPM paketa, a naša je usluga spremna za pokretanje. To se radi kroz systemd, ali prvo morate napisati malu konfiguraciju. Navedite barem URI svakog procesa. Tri su dovoljna za primjer.

$ 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

Ovdje postoji zanimljiva nijansa. Umjesto navođenja samo porta binarnog protokola, navodimo cijelu javnu adresu procesa uključujući naziv glavnog računala. Ovo je neophodno kako bi čvorovi klastera znali kako se međusobno povezati. Loša je ideja koristiti 0.0.0.0 kao advertise_uri adresu; to bi trebala biti vanjska IP adresa, a ne poveznica utičnice. Bez njega ništa neće raditi, pa vam Cartridge jednostavno neće dopustiti da pokrenete čvor s pogrešnim advertise_uri.

Sada kada je konfiguracija spremna, možete pokrenuti procese. Budući da obična systemd jedinica ne dopušta pokretanje više od jednog procesa, aplikacije na Cartridge se instaliraju tzv. instancirane jedinice koje rade ovako:

$ sudo systemctl start myapp@router
$ sudo systemctl start myapp@storage_A
$ sudo systemctl start myapp@storage_B

U konfiguraciji smo naveli HTTP port na kojem Cartridge poslužuje web sučelje - 8080. Idemo na njega i pogledajmo:

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Vidimo da iako se procesi izvode, još nisu konfigurirani. Uložak još ne zna tko kome treba replicirati i ne može sam donijeti odluku pa čeka naše akcije. Ali nemamo puno izbora: život novog klastera počinje s konfiguracijom prvog čvora. Zatim ćemo dodati ostale u klaster, dodijeliti im uloge i u ovom trenutku implementacija se može smatrati uspješno dovršenom.

Popijmo čašu vašeg omiljenog pića i opustimo se nakon dugog radnog tjedna. Aplikacija se može koristiti.

Tarantool Cartridge: dijeljenje Lua pozadine u tri retka

Rezultati

Kakvi su rezultati? Isprobajte, koristite, ostavite povratne informacije, kreirajte ulaznice na Githubu.

reference

[1] Tarantool » 2.2 » Referenca » Referenca za stijene » Modul vshard

[2] Kako smo implementirali jezgru investicijskog poslovanja Alfa-Banke na temelju Tarantoola

[3] Nova generacija arhitekture naplate: transformacija s prijelazom na Tarantool

[4] SWIM - protokol izgradnje klastera

[5] GitHub - tarantool/cartridge-cli

[6] GitHub - tarantool/uložak

Izvor: www.habr.com

Dodajte komentar