Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Pri Mail.ru Group imamo Tarantool - to je aplikacijski strežnik v Lui, ki deluje tudi kot zbirka podatkov (ali obratno?). Je hiter in kul, vendar zmogljivosti enega strežnika še vedno niso neomejene. Tudi vertikalno skaliranje ni zdravilo, zato ima Tarantool orodja za horizontalno skaliranje – modul vshard [1]. Omogoča vam razdelitev podatkov na več strežnikov, vendar se morate z njim poigrati, da ga nastavite in pripnete poslovno logiko.

Dobra novica: zbrali smo nekaj velikih posnetkov (npr [2], [3]) in ustvaril še en okvir, ki bo bistveno poenostavil rešitev tega problema.

Tarantool kartuša je nov okvir za razvoj kompleksnih porazdeljenih sistemov. Omogoča vam, da se namesto na reševanje infrastrukturnih težav osredotočite na pisanje poslovne logike. Spodaj vam bom povedal, kako deluje to ogrodje in kako z njim pisati porazdeljene storitve.

Kaj točno je problem?

Imamo tarantelo, imamo vshard - kaj več bi si lahko želeli?

Prvič, to je stvar udobja. Konfiguracija vshard je konfigurirana prek tabel Lua. Da porazdeljeni sistem več procesov Tarantool deluje pravilno, mora biti konfiguracija povsod enaka. Nihče ne želi tega narediti ročno. Zato se uporabljajo vse vrste skriptov, Ansible in sistemi za uvajanje.

Kartuša sama upravlja konfiguracijo vshard, to počne na podlagi svojega lastno porazdeljeno konfiguracijo. To je v bistvu preprosta datoteka YAML, katere kopija je shranjena v vsakem primerku Tarantoola. Poenostavitev je v tem, da ogrodje samo spremlja svojo konfiguracijo in zagotavlja, da je povsod enaka.

Drugič, spet gre za udobje. Konfiguracija vshard nima nobene zveze z razvojem poslovne logike in samo odvrača programerja od njegovega dela. Ko govorimo o arhitekturi projekta, največkrat govorimo o posameznih komponentah in njihovi interakciji. Prezgodaj je razmišljati o uvedbi gruče v 3 podatkovne centre.

Te težave smo reševali znova in znova in na neki točki nam je uspelo razviti pristop, ki je poenostavil delo z aplikacijo v celotnem življenjskem ciklu: ustvarjanje, razvoj, testiranje, CI/CD, vzdrževanje.

Cartridge uvaja koncept vloge za vsak proces Tarantool. Vloge so koncept, ki razvijalcu omogoča, da se osredotoči na pisanje kode. Vse vloge, ki so na voljo v projektu, je mogoče izvajati na eni instanci Tarantoola in to bo dovolj za teste.

Glavne lastnosti Tarantool Cartridge:

  • avtomatizirana orkestracija grozdov;
  • razširitev funkcionalnosti aplikacije z uporabo novih vlog;
  • predloga aplikacije za razvoj in uvajanje;
  • vgrajeno samodejno drobljenje;
  • integracija z ogrodjem za testiranje Luatest;
  • upravljanje gruče z uporabo spletnega uporabniškega vmesnika in API-ja;
  • orodja za pakiranje in uvajanje.

Pozdravljen, svet!

Komaj čakam, da pokažem sam okvir, zato bomo zgodbo o arhitekturi pustili za kasneje in začeli z nečim preprostim. Če predpostavimo, da je Tarantool sam že nameščen, potem je vse, kar ostane, narediti

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

Ta dva ukaza bosta namestila pripomočke ukazne vrstice in vam omogočila, da ustvarite svojo prvo aplikacijo iz predloge:

$ cartridge create --name myapp

In tole dobimo:

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/

To je repozitorij git z že pripravljenim »Hello, World!« aplikacija. Poskusimo ga zagnati takoj, ko smo predhodno namestili odvisnosti (vključno s samim ogrodjem):

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

Torej imamo eno vozlišče, ki teče za prihodnjo razdeljeno aplikacijo. Radovedni laik lahko takoj odpre spletni vmesnik, z miško konfigurira gručo enega vozlišča in uživa v rezultatu, vendar je še prezgodaj za veselje. Zaenkrat aplikacija ne more narediti nič uporabnega, zato vam bom kasneje povedal o uvajanju, zdaj pa je čas za pisanje kode.

Razvoj aplikacij

Predstavljajte si, načrtujemo projekt, ki mora prejemati podatke, jih shranjevati in sestaviti poročilo enkrat na dan.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Začnemo risati diagram in nanj postavimo tri komponente: prehod, shrambo in planer. Nadaljujemo z arhitekturo. Ker uporabljamo vshard kot shrambo, shemi dodamo vshard-router in vshard-storage. Niti prehod niti razporejevalnik ne bosta neposredno dostopala do pomnilnika; usmerjevalnik je temu namenjen, za to je bil ustvarjen.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Ta diagram še vedno ne predstavlja natančno tega, kar bomo zgradili v projektu, ker so komponente videti abstraktno. Še vedno moramo videti, kako bo to projicirano na pravi Tarantool - združimo naše komponente po postopku.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Nima smisla obdržati vshard-router in prehod na ločenih instancah. Zakaj moramo še enkrat brskati po omrežju, če je to že odgovornost usmerjevalnika? Izvajati jih je treba znotraj istega procesa. To pomeni, da sta prehod in vshard.router.cfg inicializirana v enem procesu in ju pustita, da delujeta lokalno.

V fazi načrtovanja je bilo priročno delati s tremi komponentami, vendar jaz kot razvijalec med pisanjem kode ne želim razmišljati o zagonu treh primerkov Tarnatoola. Opraviti moram teste in preveriti, ali sem pravilno napisal prehod. Ali pa bi morda želel predstaviti funkcijo svojim kolegom. Zakaj bi moral iti skozi težave z uvajanjem treh kopij? Tako se je rodil koncept vlog. Vloga je običajni modul luash, katerega življenjski cikel upravlja Cartridge. V tem primeru so štirje - prehod, usmerjevalnik, shramba, razporejevalnik. Morda jih bo več v drugem projektu. Vse vloge se lahko izvajajo v enem procesu in to bo dovolj.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

In ko gre za uvajanje v uprizoritev ali produkcijo, bomo vsakemu procesu Tarantool dodelili svoj niz vlog, odvisno od zmogljivosti strojne opreme:

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Upravljanje topologije

Informacije o tem, kje se izvajajo katere vloge, morajo biti nekje shranjene. In to »nekje« je porazdeljena konfiguracija, ki sem jo že omenil zgoraj. Najpomembnejša stvar pri tem je topologija gruče. Tukaj so 3 replikacijske skupine 5 procesov Tarantool:

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Ne želimo izgubiti podatkov, zato z informacijami o tekočih procesih ravnamo skrbno. Kartuša spremlja konfiguracijo z uporabo dvofazne potrditve. Ko želimo posodobiti konfiguracijo, najprej preveri, ali so vsi primerki na voljo in pripravljeni sprejeti novo konfiguracijo. Po tem druga faza uporabi konfiguracijo. Torej, tudi če se izkaže, da en izvod začasno ni na voljo, se ne bo zgodilo nič slabega. Konfiguracija preprosto ne bo uporabljena in vnaprej boste videli napako.

Tudi v razdelku o topologiji je naveden tako pomemben parameter, kot je vodja vsake replikacijske skupine. Običajno je to kopija, ki se snema. Ostali so najpogosteje samo za branje, čeprav lahko obstajajo izjeme. Včasih se pogumni razvijalci ne bojijo konfliktov in lahko zapisujejo podatke v več replik vzporedno, vendar obstajajo nekatere operacije, ki jih ne glede na vse ne bi smeli izvajati dvakrat. Za to obstaja znak vodje.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Življenje vlog

Da bi v takšni arhitekturi obstajala abstraktna vloga, jo mora okvir nekako upravljati. Seveda se nadzor izvede brez ponovnega zagona procesa Tarantool. Za upravljanje vlog so na voljo 4 povratni klici. Kartuša sama jih bo poklicala glede na to, kaj je zapisano v njeni porazdeljeni konfiguraciji, s čimer bo konfiguracijo uporabila za določene vloge.

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

Vsaka vloga ima svojo funkcijo init. Pokliče se enkrat, ko je vloga omogočena ali ko se Tarantool znova zažene. Tam je priročno na primer inicializirati box.space.create ali pa lahko razporejevalnik zažene neko vlakno v ozadju, ki bo opravilo delo v določenih časovnih intervalih.

Ena funkcija init morda ne bo dovolj. Kartuša omogoča vlogam, da izkoristijo porazdeljeno konfiguracijo, ki jo uporablja za shranjevanje topologije. V isti konfiguraciji lahko deklariramo nov razdelek in vanj shranimo delček poslovne konfiguracije. V mojem primeru je to lahko podatkovna shema ali nastavitve urnika za vlogo načrtovalca.

Grozdni klici validate_config и apply_config vsakič, ko se porazdeljena konfiguracija spremeni. Ko se konfiguracija uporabi z dvofazno potrditvijo, gruča preveri, ali je vsaka vloga pripravljena sprejeti to novo konfiguracijo, in po potrebi sporoči uporabniku napako. Ko se vsi strinjajo, da je konfiguracija normalna, potem je apply_config.

Tudi vloge imajo metodo stop, ki je potreben za čiščenje izpisa vloge. Če rečemo, da razporejevalnik na tem strežniku ni več potreben, lahko ustavi tista vlakna, s katerimi je začel init.

Vloge lahko medsebojno delujejo. Navajeni smo pisanja funkcijskih klicev v Lui, vendar se lahko zgodi, da dani proces nima vloge, ki jo potrebujemo. Za lažje klice po omrežju uporabljamo pomožni modul rpc (remote procedure call), ki je zgrajen na osnovi standardnega netboxa, vgrajenega v Tarantool. To je lahko uporabno, če želi na primer vaš prehod neposredno od načrtovalca zahtevati, da opravi delo zdaj, namesto da čaka en dan.

Druga pomembna točka je zagotavljanje tolerance napak. Kartuša uporablja protokol SWIM za spremljanje zdravja [4]. Skratka, procesi med seboj izmenjujejo »govorice« prek UDP - vsak proces svojim sosedom sporoči najnovejše novice, ti pa se odzovejo. Če nenadoma ne pride odgovor, Tarantool začne sumiti, da je nekaj narobe, in čez nekaj časa recitira smrt in začne vsem pripovedovati to novico.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Na podlagi tega protokola Cartridge organizira samodejno obdelavo napak. Vsak proces spremlja svoje okolje in če se vodilni nenadoma neha odzivati, lahko replika prevzame njegovo vlogo, Cartridge pa ustrezno konfigurira tekoče vloge.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Pri tem morate biti previdni, saj lahko pogosto preklapljanje naprej in nazaj povzroči spore podatkov med replikacijo. Seveda ne bi smeli naključno omogočiti samodejnega preklopa. Jasno moramo razumeti, kaj se dogaja, in biti prepričani, da se replikacija ne bo prekinila, ko bo vodja obnovljen in mu bo vrnjena krona.

Iz vsega tega boste morda dobili občutek, da so vloge podobne mikrostoritvam. V nekem smislu so prav to, samo kot moduli znotraj procesov Tarantool. Obstaja pa tudi vrsta temeljnih razlik. Prvič, vse projektne vloge morajo živeti v isti osnovi kode. In vsi Tarantool procesi bi se morali zagnati iz iste kodne baze, da ne bi prišlo do presenečenj, kot so tista, ko poskušamo inicializirati razporejevalnik, pa ga preprosto ni. Prav tako ne smete dovoliti razlik v različicah kode, ker je obnašanje sistema v takšni situaciji zelo težko predvideti in odpraviti napake.

Za razliko od Dockerja ne moremo preprosto vzeti "slike" vloge, jo odnesti na drug stroj in tam zagnati. Naše vloge niso tako izolirane kot vsebniki Docker. Prav tako ne moremo izvajati dveh enakih vlog na enem primerku. Vloga bodisi obstaja ali pa je ne; v nekem smislu je ena oseba. In tretjič, vloge morajo biti enake znotraj celotne replikacijske skupine, saj bi bilo sicer absurdno – podatki so isti, konfiguracija pa drugačna.

Orodja za uvajanje

Obljubil sem, da bom pokazal, kako Cartridge pomaga pri uvajanju aplikacij. Da bi olajšali življenje drugim, okvir vsebuje pakete RPM:

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

Nameščen paket vsebuje skoraj vse, kar potrebujete: tako aplikacijo kot nameščene odvisnosti. Tarantool bo prispel tudi na strežnik kot odvisnost od paketa RPM in naša storitev je pripravljena za zagon. To se naredi prek systemd, vendar morate najprej napisati nekaj konfiguracije. Določite vsaj URI vsakega procesa. Dovolj so na primer trije.

$ 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

Tukaj je zanimiva niansa. Namesto da podamo samo vrata binarnega protokola, podamo celoten javni naslov procesa, vključno z imenom gostitelja. To je potrebno, da se vozlišča gruče med seboj vedo, kako se povezati. Slaba ideja je, da kot naslov advertise_uri uporabite 0.0.0.0; to bi moral biti zunanji naslov IP in ne vezava vtičnice. Brez tega nič ne bo delovalo, zato vam Cartridge preprosto ne bo dovolil zagnati vozlišča z napačnim advertise_uri.

Zdaj, ko je konfiguracija pripravljena, lahko začnete s procesi. Ker navadna sistemska enota ne dovoljuje zagona več kot enega procesa, se aplikacije na Cartridge namestijo po t.i. instancirane enote, ki delujejo takole:

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

V konfiguraciji smo določili vrata HTTP, na katerih Cartridge streže spletni vmesnik - 8080. Pojdimo nanj in si oglejmo:

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Vidimo, da čeprav se procesi izvajajo, še niso konfigurirani. Kartuša še ne ve, kdo naj se pri kom replicira in se ne more sama odločiti, zato čaka na naša dejanja. Vendar nimamo veliko izbire: življenje nove gruče se začne s konfiguracijo prvega vozlišča. Nato bomo druge dodali v gručo, jim dodelili vloge in na tej točki se lahko šteje, da je uvedba uspešno zaključena.

Natočimo si kozarček vaše najljubše pijače in se sprostimo po dolgem delovnem tednu. Aplikacijo je mogoče uporabiti.

Tarantool Cartridge: razdelitev ozadja Lua v tri vrstice

Rezultati

Kakšni so rezultati? Preizkusite, uporabite, pustite povratne informacije, ustvarite vstopnice na Githubu.

reference

[1] Tarantool » 2.2 » Referenca » Referenca kamnin » Modul vshard

[2] Kako smo implementirali jedro investicijskega poslovanja Alfa-Bank, ki temelji na Tarantoolu

[3] Nova generacija obračunske arhitekture: transformacija s prehodom na Tarantool

[4] SWIM - protokol gradnje gruče

[5] GitHub - tarantool/cartridge-cli

[6] GitHub - tarantool/kartuša

Vir: www.habr.com

Dodaj komentar