Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

U Mail.ru Group imamo Tarantool - ovo je server aplikacija u Lua-i, koji također služi kao baza podataka (ili obrnuto?). Brz je i cool, ali mogućnosti jednog servera i dalje nisu neograničene. Vertikalno skaliranje također nije lijek, tako da Tarantool ima alate za horizontalno skaliranje - modul vshard [1]. Omogućava vam da dijelite podatke na nekoliko servera, ali morate se pomučiti da biste ga postavili i priložili poslovnu logiku.

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

Tarantool Cartridge je novi okvir za razvoj složenih distribuiranih sistema. Omogućava vam da se fokusirate na pisanje poslovne logike umjesto na rješavanje infrastrukturnih problema. Ispod reza ću vam reći kako ovaj framework radi i kako pisati distribuirane servise koristeći ga.

Šta je tačno problem?

Imamo tarantulu, imamo vshard - šta više želite?

Prije svega, to je stvar pogodnosti. Konfiguracija vshard-a se konfiguriše preko Lua tabela. Da bi distribuirani sistem višestrukih Tarantool procesa ispravno radio, konfiguracija mora biti svuda ista. Niko ne želi ovo da radi ručno. Stoga se koriste sve vrste skripti, Ansible i sistemi za implementaciju.

Cartridge sama upravlja konfiguracijom vshard, to radi na osnovu svoje vlastitu distribuiranu konfiguraciju. To je u suštini jednostavna YAML datoteka, čija je kopija pohranjena u svakoj instanci Tarantool-a. Pojednostavljenje je da sam okvir prati svoju konfiguraciju i osigurava da je svugdje isti.

Drugo, to je opet pitanje pogodnosti. Konfiguracija vshard nema nikakve veze sa razvojem poslovne logike i samo odvlači programera od njegovog posla. 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 data centra.

Rešavali smo ove probleme iznova i iznova, i u nekom trenutku smo uspeli da razvijemo pristup koji je pojednostavio rad sa aplikacijom kroz njen čitav životni ciklus: kreiranje, razvoj, testiranje, CI/CD, održavanje.

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

Ključne karakteristike Tarantool Cartridgea:

  • automatizovana klaster orkestracija;
  • proširenje funkcionalnosti aplikacije korištenjem novih uloga;
  • predložak aplikacije za razvoj i implementaciju;
  • ugrađeno automatsko dijeljenje;
  • integracija sa Luatest okvirom za testiranje;
  • upravljanje klasterima koristeći WebUI i API;
  • alati za pakovanje i implementaciju.

Zdravo svijete!

Jedva čekam da pokažem sam okvir, pa ćemo priču o arhitekturi ostaviti za kasnije i početi s nečim jednostavnim. Ako pretpostavimo da je sam Tarantool već instaliran, onda ostaje samo da se uradi

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

Ove dvije naredbe će instalirati pomoćne programe komandne linije i omogućiti vam da kreirate svoju prvu aplikaciju iz predloška:

$ cartridge create --name myapp

I evo šta dobijamo:

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 repozitorijum sa gotovim „Zdravo, svet!“ aplikacija. Pokušajmo ga pokrenuti odmah, nakon što smo prethodno instalirali zavisnosti (uključujući i sam okvir):

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

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

Razvoj aplikacija

Zamislite samo, mi dizajniramo projekat koji mora primati podatke, čuvati ih i praviti izvještaj jednom dnevno.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Počinjemo crtati dijagram i na njega postavljamo tri komponente: gateway, skladište i planer. Dalje radimo na arhitekturi. Pošto koristimo vshard kao skladište, šemi dodajemo vshard-router i vshard-storage. Ni gateway ni planer neće direktno pristupiti skladištu; za to je ruter, za to je stvoren.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Ovaj dijagram još uvijek ne predstavlja baš ono što ćemo graditi u projektu jer komponente izgledaju apstraktno. Još treba da vidimo kako će se ovo projektovati na pravi Tarantool - grupišimo naše komponente prema procesu.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

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 u okviru istog procesa. Odnosno, i gateway i vshard.router.cfg se inicijaliziraju u jednom procesu i puštaju ih da komuniciraju lokalno.

U fazi dizajna bilo je zgodno raditi sa tri komponente, ali ja, kao programer, dok pišem kod, ne želim razmišljati o pokretanju tri instance Tarnatool-a. Moram da pokrenem testove i proverim da li sam ispravno napisao gateway. Ili možda želim da demonstriram neku funkciju svojim kolegama. Zašto bih morao prolaziti kroz gnjavažu oko postavljanja tri kopije? Tako je rođen koncept uloga. Uloga je običan luash modul čijim životnim ciklusom upravlja Cartridge. U ovom primjeru postoje četiri od njih - gateway, ruter, memorija, planer. Možda ih ima više u nekom drugom projektu. Sve uloge se mogu pokrenuti u jednom procesu i to će biti dovoljno.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

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

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Upravljanje topologijom

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

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Ne želimo da izgubimo podatke, stoga pažljivo postupamo sa informacijama o pokrenutim procesima. Cartridge prati konfiguraciju koristeći dvofazno urezivanje. Jednom kada želimo ažurirati konfiguraciju, prvo provjerava da li su sve instance dostupne i spremne da prihvate novu konfiguraciju. Nakon toga, druga faza primjenjuje konfiguraciju. Stoga, čak i ako se pokaže da je jedan primjerak privremeno nedostupan, ništa loše se neće dogoditi. Konfiguracija se jednostavno neće primijeniti i unaprijed ćete vidjeti grešku.

Također u odjeljku topologije, naznačen je tako važan parametar kao što je vođa svake grupe replikacije. Obično je to kopija koja se snima. Ostali su najčešće samo za čitanje, iako mogu postojati izuzeci. Ponekad se hrabri programeri ne boje konflikata i mogu paralelno pisati podatke u nekoliko replika, ali postoje neke operacije koje, bez obzira na sve, ne bi trebalo izvoditi dvaput. Za to postoji znak vođe.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Život uloga

Da bi apstraktna uloga postojala u takvoj arhitekturi, okvir mora nekako upravljati njima. Naravno, kontrola se javlja bez ponovnog pokretanja Tarantool procesa. Postoje 4 povratna poziva za upravljanje ulogama. Sam Cartridge će ih pozvati ovisno o tome što je napisano u njegovoj distribuiranoj konfiguraciji, primjenjujući tako konfiguraciju 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 ponovo pokrene. Tamo je zgodno, na primjer, inicijalizirati box.space.create, ili planer može pokrenuti neka pozadinska vlakna koja će obavljati posao u određenim vremenskim intervalima.

Jedna funkcija init možda neće biti dovoljno. Cartridge omogućava ulogama da iskoriste prednosti 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, ovo bi mogla biti šema podataka ili postavke rasporeda za ulogu planera.

Cluster calls validate_config и apply_config svaki put kada se distribuirana konfiguracija promijeni. Kada se konfiguracija primjenjuje dvofaznim urezivanjem, klaster provjerava da li je svaka uloga spremna prihvatiti ovu novu konfiguraciju i, ako je potrebno, prijavljuje grešku korisniku. Kada se svi slože da je konfiguracija normalna, onda apply_config.

Također uloge imaju metodu stop, koji je potreban za čišćenje izlaza uloge. Ako kažemo da planer više nije potreban na ovom serveru, on može zaustaviti ta vlakna koja je počeo koristiti init.

Uloge mogu biti u interakciji jedna s drugom. Navikli smo pisati pozive funkcija u Lua-i, ali može se dogoditi da određeni proces nema ulogu koja nam je potrebna. Da bismo olakšali pozive preko mreže, koristimo pomoćni modul rpc (remote procedure call), koji je izgrađen na bazi standardnog netboxa ugrađenog u Tarantool. Ovo može biti korisno ako, na primjer, vaš gateway želi direktno zatražiti od planera da obavi posao upravo sada, umjesto da čeka dan.

Još jedna važna tačka je osiguranje tolerancije grešaka. Cartridge 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 odgovor ne dođe, Tarantool počinje sumnjati da nešto nije u redu, a nakon nekog vremena recituje smrt i počinje saopštavati svima okolo ovu vijest.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Na osnovu ovog protokola, Cartridge organizira automatsku obradu kvarova. Svaki proces prati svoje okruženje, i ako vođa iznenada prestane da odgovara, replika može preuzeti njegovu ulogu, a Cartridge u skladu s tim konfiguriše pokrenute uloge.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Ovdje morate biti oprezni, jer često prebacivanje naprijed-nazad može dovesti do sukoba podataka tokom replikacije. Naravno, ne biste trebali nasumično omogućiti automatski prelazak na grešku. Moramo jasno razumjeti šta se dešava i biti sigurni da se replikacija neće prekinuti nakon što se vođa vrati i kruna mu bude vraćena.

Iz svega ovoga možete imati 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 fundamentalnih razlika. Prvo, sve projektne uloge moraju živjeti u istoj bazi koda. A sve Tarantool procese treba pokrenuti iz iste baze koda, kako ne bi bilo iznenađenja poput onih kada pokušamo inicijalizirati planer, ali on jednostavno ne postoji. Takođe, ne treba dozvoliti razlike u verzijama koda, jer je ponašanje sistema u takvoj situaciji veoma teško predvideti i otkloniti greške.

Za razliku od Dockera, ne možemo samo preuzeti ulogu "image", odnijeti je na drugu mašinu i tamo pokrenuti. Naše uloge nisu tako izolovane kao Docker kontejneri. Također, ne možemo pokrenuti dvije identične uloge na jednoj instanci. Uloga ili postoji ili ne postoji; u određenom smislu, ona je pojedinačna. I treće, uloge moraju biti iste unutar cijele grupe za replikaciju, jer bi inače bilo apsurdno - podaci su isti, ali je konfiguracija drugačija.

Alati za implementaciju

Obećao sam da ću pokazati kako Cartridge pomaže u implementaciji aplikacija. Da bi drugima olakšao život, framework pakete 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 server kao zavisnost od RPM paketa, a naš servis je spreman za pokretanje. Ovo se radi preko systemd-a, ali prvo morate napisati malu konfiguraciju. U najmanju ruku navedite URI svakog procesa. Na primjer, tri su dovoljna.

$ 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 da specificiramo samo port binarnog protokola, specificiramo cijelu javnu adresu procesa uključujući ime hosta. Ovo je neophodno kako bi čvorovi klastera znali kako da se povežu jedni s drugima. Loša je ideja koristiti 0.0.0.0 kao advertise_uri adresu; to bi trebala biti vanjska IP adresa, a ne veza za socket. Bez toga ništa neće raditi, tako da vam Cartridge jednostavno neće dozvoliti da pokrenete čvor sa pogrešnim advertise_uri.

Sada kada je konfiguracija spremna, možete pokrenuti procese. Pošto obična systemd jedinica ne dozvoljava 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 opslužuje web sučelje - 8080. Idemo do njega i bacimo pogled:

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Vidimo da iako su procesi pokrenuti, oni još nisu konfigurisani. Uložak još ne zna ko bi s kim trebao replicirati i ne može sam donijeti odluku, pa čeka naše akcije. Ali nemamo mnogo izbora: život novog klastera počinje konfiguracijom prvog čvora. Zatim ćemo dodati ostale u klaster, dodijeliti im uloge i u ovom trenutku se implementacija može smatrati uspješno završenom.

Nalijmo čašu vašeg omiljenog pića i opustimo se nakon duge radne sedmice. Aplikacija se može koristiti.

Tarantool Cartridge: razbijanje Lua pozadine u tri reda

Ishodi

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

reference

[1] Tarantool » 2.2 » Reference » Rocks reference » Module vshard

[2] Kako smo implementirali srž investicionog poslovanja Alfa-Bank zasnovanog na Tarantoolu

[3] Arhitektura naplate nove generacije: transformacija sa prelaskom na Tarantool

[4] SWIM - protokol izgradnje klastera

[5] GitHub - tarantool/cartridge-cli

[6] GitHub - tarantool/kartridž

izvor: www.habr.com

Dodajte komentar