Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Mail.ru Groupissa meillä on Tarantool - tämä on Luan sovelluspalvelin, joka toimii myös tietokantana (tai päinvastoin?). Se on nopea ja siisti, mutta yhden palvelimen ominaisuudet eivät silti ole rajattomat. Pystyskaalaus ei myöskään ole ihmelääke, joten Tarantoolilla on työkaluja vaakasuoraan skaalauson - vshard-moduuli [1]. Sen avulla voit sirpata tietoja useiden palvelimien välillä, mutta sinun on työskenneltävä sen kanssa määrittääksesi sen ja liittääksesi liiketoimintalogiikan.

Hyviä uutisia: olemme keränneet isoja otoksia (esim [2], [3]) ja loi toisen kehyksen, joka yksinkertaistaa merkittävästi tämän ongelman ratkaisua.

Tarantool patruuna on uusi kehys monimutkaisten hajautettujen järjestelmien kehittämiseen. Sen avulla voit keskittyä liiketoimintalogiikan kirjoittamiseen infrastruktuuriongelmien ratkaisemisen sijaan. Leikkauksen alla kerron kuinka tämä kehys toimii ja kuinka hajautettuja palveluita kirjoitetaan sen avulla.

Ja mikä se ongelma oikein on?

Meillä on tarantula, meillä on vshard - mitä muuta voit haluta?

Ensinnäkin se on mukavuuskysymys. Vshard-kokoonpano määritetään Lua-taulukoiden kautta. Jotta hajautettu järjestelmä, jossa on useita Tarantool-prosesseja, toimisi oikein, kokoonpanon on oltava sama kaikkialla. Kukaan ei halua tehdä tätä manuaalisesti. Siksi käytetään kaikenlaisia ​​komentosarjoja, Ansible- ja käyttöönottojärjestelmiä.

Patruuna itse hallitsee vshard-kokoonpanoa, se tekee tämän sen perusteella oma hajautettu kokoonpano. Se on pohjimmiltaan yksinkertainen YAML-tiedosto, jonka kopio on tallennettu jokaiseen Tarantool-instanssiin. Yksinkertaistettuna on, että kehys itse valvoo kokoonpanoaan ja varmistaa, että se on sama kaikkialla.

Toiseksi, se on jälleen mukavuuskysymys. vshard-kokoonpanolla ei ole mitään tekemistä liiketoimintalogiikan kehittämisen kanssa ja se vain häiritsee ohjelmoijaa hänen työstään. Kun puhumme projektin arkkitehtuurista, puhumme useimmiten yksittäisistä komponenteista ja niiden vuorovaikutuksesta. On liian aikaista ajatella klusterin käyttöönottoa kolmeen palvelinkeskukseen.

Ratkaisimme nämä ongelmat yhä uudestaan ​​ja uudestaan, ja jossain vaiheessa onnistuimme kehittämään lähestymistapaa, joka yksinkertaisti työskentelyä sovelluksen kanssa sen koko elinkaaren ajan: luominen, kehitys, testaus, CI/CD, ylläpito.

Patruuna esittelee roolin käsitteen jokaiselle Tarantool-prosessille. Roolit ovat konsepti, jonka avulla kehittäjä voi keskittyä koodin kirjoittamiseen. Kaikki projektissa olevat roolit voidaan ajaa yhdellä Tarantool-instanssilla, ja tämä riittää testeihin.

Tarantool-patruunan tärkeimmät ominaisuudet:

  • automaattinen klusterin orkestrointi;
  • sovelluksen toiminnallisuuden laajentaminen uusilla rooleilla;
  • sovellusmalli kehitystä ja käyttöönottoa varten;
  • sisäänrakennettu automaattinen sirpalointi;
  • integrointi Luatest-testauskehykseen;
  • klusterin hallinta WebUI:n ja API:n avulla;
  • pakkaus- ja käyttöönottotyökalut.

Hei maailma!

En malta odottaa, että pääsen esittelemään itse kehyksen, joten jätämme tarinan arkkitehtuurista myöhemmäksi ja aloitamme jostain yksinkertaisesta. Jos oletetaan, että Tarantool itse on jo asennettu, ei jää muuta kuin tehdä

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

Nämä kaksi komentoa asentavat komentorivin apuohjelmat ja antavat sinun luoda ensimmäisen sovelluksesi mallista:

$ cartridge create --name myapp

Ja tämän saamme:

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/

Tämä on git-arkisto, jossa on valmis "Hello, World!" sovellus. Yritetään suorittaa se heti, kun olet aiemmin asentanut riippuvuudet (mukaan lukien itse kehys):

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

Joten meillä on yksi solmu käynnissä tulevaa sirpaloitua sovellusta varten. Utelias maallikko voi heti avata verkkokäyttöliittymän, konfiguroida yhden solmun klusterin hiirellä ja nauttia tuloksesta, mutta on liian aikaista iloita. Toistaiseksi sovellus ei voi tehdä mitään hyödyllistä, joten kerron käyttöönotosta myöhemmin, mutta nyt on aika kirjoittaa koodi.

Sovellus kehitys

Kuvittele vain, suunnittelemme projektia, jonka täytyy vastaanottaa dataa, tallentaa se ja rakentaa raportti kerran päivässä.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Aloitamme kaavion piirtämisen ja asetamme siihen kolme komponenttia: yhdyskäytävä, tallennustila ja ajastin. Työskentelemme arkkitehtuuria edelleen. Koska käytämme vshardia tallennustilana, lisäämme vshard-router ja vshard-storage järjestelmään. Yhdyskäytävä tai ajastin eivät pääse suoraan tallennustilaan; sitä varten reititin on tarkoitettu, sitä varten se luotiin.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Tämä kaavio ei vieläkään edusta tarkasti sitä, mitä rakennamme projektissa, koska komponentit näyttävät abstrakteilta. Meidän on vielä nähtävä, kuinka tämä heijastetaan todelliseen Tarantooliin - ryhmitellään komponentit prosessien mukaan.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Ei ole mitään järkeä pitää vshard-router ja gateway erillisissä tapauksissa. Miksi meidän pitää surffata verkossa vielä kerran, jos tämä on jo reitittimen vastuulla? Ne on suoritettava saman prosessin puitteissa. Toisin sanoen sekä yhdyskäytävä että vshard.router.cfg alustetaan yhdessä prosessissa, ja ne voivat olla vuorovaikutuksessa paikallisesti.

Suunnitteluvaiheessa oli kätevää työskennellä kolmen komponentin kanssa, mutta minä kehittäjänä en koodia kirjoittaessani halua ajatella kolmen Tarnatoolin julkaisun käynnistämistä. Minun on suoritettava testit ja tarkistettava, että kirjoitin yhdyskäytävän oikein. Tai ehkä haluan esitellä ominaisuutta kollegoilleni. Miksi minun pitäisi käydä läpi vaivaa ottaa käyttöön kolme kopiota? Näin syntyi käsitys roolista. Rooli on tavallinen luash-moduuli, jonka elinkaarta hallitsee Cartridge. Tässä esimerkissä niitä on neljä - yhdyskäytävä, reititin, tallennustila, ajoitus. Toisessa projektissa voi olla enemmän. Kaikki roolit voidaan suorittaa yhdessä prosessissa, ja tämä riittää.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Ja kun on kyse vaiheittaisesta tai tuotannosta, annamme jokaiselle Tarantool-prosessille omat roolinsa laitteiston ominaisuuksien mukaan:

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Topologian hallinta

Tietoa siitä, missä roolit ovat käynnissä, on tallennettava jonnekin. Ja tämä "jossain" on hajautettu kokoonpano, jonka mainitsin jo edellä. Tärkein asia siinä on klusterin topologia. Tässä on 3 replikointiryhmää 5 Tarantool-prosessista:

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Emme halua menettää tietoja, joten käsittelemme tietoja käynnissä olevista prosesseista huolella. Kasetti seuraa kokoonpanoa kaksivaiheisen vahvistuksen avulla. Kun haluamme päivittää kokoonpanon, se tarkistaa ensin, että kaikki esiintymät ovat saatavilla ja valmiita hyväksymään uudet asetukset. Tämän jälkeen toinen vaihe ottaa käyttöön konfiguroinnin. Näin ollen, vaikka yksi kopio osoittautuisi tilapäisesti poissa käytöstä, mitään pahaa ei tapahdu. Määritystä ei yksinkertaisesti oteta käyttöön ja näet virheilmoituksen etukäteen.

Myös topologia-osiossa on merkitty niin tärkeä parametri kuin kunkin replikointiryhmän johtaja. Yleensä tämä on kopio, joka tallennetaan. Loput ovat useimmiten vain luku -muotoisia, vaikka poikkeuksiakin saattaa olla. Joskus rohkeat kehittäjät eivät pelkää ristiriitoja ja voivat kirjoittaa tietoja useisiin replikoihin rinnakkain, mutta on joitain toimintoja, joita ei kuitenkaan pitäisi suorittaa kahdesti. Tätä varten on johtajan merkki.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Roolien elämä

Jotta abstrakti rooli olisi olemassa tällaisessa arkkitehtuurissa, kehyksen on hallittava niitä jollakin tavalla. Luonnollisesti ohjaus tapahtuu käynnistämättä Tarantool-prosessia uudelleen. Roolien hallintaa varten on 4 takaisinsoittoa. Kasetti itse kutsuu niitä sen mukaan, mitä sen hajautettuun kokoonpanoon on kirjoitettu, ja soveltaa siten määritystä tiettyihin rooleihin.

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

Jokaisella roolilla on tehtävänsä init. Sitä kutsutaan kerran joko roolin ollessa käytössä tai kun Tarantool käynnistetään uudelleen. Siellä on kätevää alustaa esimerkiksi box.space.create, tai ajastin voi käynnistää jonkin taustakuidun, joka tekee työtä tietyin aikavälein.

Yksi toiminto init ei ehkä riitä. Kasetin avulla roolit voivat hyödyntää hajautettua kokoonpanoa, jota se käyttää topologian tallentamiseen. Voimme ilmoittaa uuden osion samassa kokoonpanossa ja tallentaa siihen osan yritysmäärityksestä. Esimerkissäni tämä voi olla dataskeema tai ajoitusroolin aikatauluasetukset.

Klusteripuhelut validate_config и apply_config aina, kun hajautettu kokoonpano muuttuu. Kun määritystä käytetään kaksivaiheisella vahvistuksella, klusteri tarkistaa, että jokainen rooli on valmis hyväksymään tämän uuden määrityksen, ja raportoi tarvittaessa virheestä käyttäjälle. Kun kaikki ovat yhtä mieltä siitä, että kokoonpano on normaali, apply_config.

Myös rooleilla on menetelmä stop, jota tarvitaan roolin tulosteen puhdistamiseen. Jos sanomme, että ajastinta ei enää tarvita tällä palvelimella, se voi pysäyttää ne kuidut, joilla se aloitti init.

Roolit voivat olla vuorovaikutuksessa keskenään. Olemme tottuneet kirjoittamaan funktiokutsuja Luassa, mutta voi käydä niin, että tietyllä prosessilla ei ole tarvitsemaamme roolia. Verkkopuheluiden helpottamiseksi käytämme rpc-apumoduulia (remote procedure call), joka on rakennettu Tarantooliin sisäänrakennetun standardin netboxin pohjalta. Tästä voi olla hyötyä, jos esimerkiksi yhdyskäytäväsi haluaa suoraan pyytää ajoittajaa tekemään työn juuri nyt sen sijaan, että odotat päivän.

Toinen tärkeä seikka on vikasietoisuuden varmistaminen. Patruuna käyttää SWIM-protokollaa kunnon seuraamiseen [4]. Lyhyesti sanottuna prosessit vaihtavat "huhuja" toistensa kanssa UDP:n kautta – jokainen prosessi kertoo naapureilleen viimeisimmät uutiset, ja he vastaavat. Jos vastausta ei yhtäkkiä tule, Tarantool alkaa epäillä, että jotain on vialla, ja hetken kuluttua se lausuu kuolemasta ja alkaa kertoa kaikille ympärillä oleville uutisille.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Tämän protokollan perusteella Cartridge järjestää automaattisen viankäsittelyn. Jokainen prosessi tarkkailee ympäristöään, ja jos johtaja yhtäkkiä lakkaa vastaamasta, replika voi ottaa roolinsa ja Cartridge määrittää käynnissä olevat roolit vastaavasti.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Sinun on oltava varovainen tässä, koska toistuva vaihtaminen edestakaisin voi aiheuttaa tietoristiriitoja replikoinnin aikana. Tietenkään sinun ei pitäisi ottaa automaattista vikasietoa satunnaisesti käyttöön. Meidän on ymmärrettävä selvästi, mitä tapahtuu, ja oltava varmoja, että replikaatio ei katkea sen jälkeen, kun johtaja on palautettu ja kruunu palautetaan hänelle.

Kaikesta tästä voi tulla tunne, että roolit ovat samanlaisia ​​kuin mikropalvelut. Tietyssä mielessä ne ovat juuri sellaisia, vain moduuleina Tarantool-prosessien sisällä. Mutta on myös monia perustavanlaatuisia eroja. Ensinnäkin kaikkien projektiroolien on oltava samassa koodikannassa. Ja kaikki Tarantool-prosessit tulisi käynnistää samasta koodikannasta, jotta ei tule yllätyksiä, kuten ne, kun yritämme alustaa ajoitinta, mutta sitä ei yksinkertaisesti ole olemassa. Sinun ei myöskään pidä sallia eroja koodiversioissa, koska järjestelmän käyttäytymistä tällaisessa tilanteessa on erittäin vaikea ennustaa ja korjata.

Toisin kuin Docker, emme voi vain ottaa roolikuvaa, viedä sitä toiselle koneelle ja ajaa sitä siellä. Roolimme eivät ole yhtä eristettyjä kuin Docker-kontit. Emme myöskään voi suorittaa kahta identtistä roolia yhdessä esiintymässä. Rooli joko on olemassa tai ei ole; tietyssä mielessä se on yksittäinen. Ja kolmanneksi, roolien on oltava samat koko replikointiryhmässä, koska muuten se olisi absurdia - tiedot ovat samat, mutta konfiguraatio on erilainen.

Käyttöönottotyökalut

Lupasin näyttää, kuinka Cartridge auttaa ottamaan sovelluksia käyttöön. Helpottaakseen muiden elämää puitteet pakkaavat RPM-paketit:

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

Asennettu paketti sisältää melkein kaiken tarvitsemasi: sekä sovelluksen että asennetut riippuvuudet. Tarantool saapuu palvelimelle myös RPM-paketin riippuvuutena ja palvelumme on valmis käynnistymään. Tämä tehdään systemd:n ​​kautta, mutta ensin sinun on kirjoitettava vähän asetuksia. Määritä vähintään kunkin prosessin URI. Esimerkiksi kolme riittää.

$ 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

Tässä on mielenkiintoinen vivahde. Sen sijaan, että määrittäisimme vain binaariprotokollaportin, määritämme prosessin koko julkisen osoitteen, mukaan lukien isäntänimi. Tämä on välttämätöntä, jotta klusterin solmut tietävät kuinka muodostaa yhteyden toisiinsa. On huono idea käyttää 0.0.0.0:aa advertise_uri-osoitteena; sen pitäisi olla ulkoinen IP-osoite, ei socket bind. Ilman sitä mikään ei toimi, joten Cartridge ei yksinkertaisesti anna sinun käynnistää solmua väärällä mainos_urilla.

Nyt kun kokoonpano on valmis, voit aloittaa prosessit. Koska tavallinen järjestelmäyksikkö ei salli useamman kuin yhden prosessin käynnistymistä, kasetin sovellukset asennetaan ns. instantoidut yksiköt, jotka toimivat näin:

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

Määritimme määrityksessä HTTP-portin, jossa Cartridge palvelee verkkokäyttöliittymää - 8080. Mennään siihen ja katsotaan:

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Näemme, että vaikka prosessit ovat käynnissä, niitä ei ole vielä määritetty. Patruuna ei vielä tiedä, kenen pitäisi kopioida kenen kanssa eikä voi tehdä päätöstä itse, joten se odottaa toimiamme. Mutta meillä ei ole paljon valinnanvaraa: uuden klusterin käyttöikä alkaa ensimmäisen solmun määrittämisestä. Sitten lisäämme muut klusteriin, annamme heille roolit, ja tässä vaiheessa käyttöönotto voidaan katsoa onnistuneesti suoritetuksi.

Kaada lasillinen suosikkijuomaasi ja rentoudu pitkän työviikon jälkeen. Sovellusta voidaan käyttää.

Tarantool-kasetti: Lua-taustajärjestelmän sirpalointi kolmeen riviin

Tulokset

Mitkä ovat tulokset? Kokeile, käytä, jätä palautetta, luo lippuja Githubissa.

viittaukset

[1] Tarantool » 2.2 » Reference » Rocks referenssi » Moduuli vshard

[2] Kuinka toteutimme Alfa-Pankin Tarantooliin perustuvan sijoitustoiminnan ytimen

[3] Uuden sukupolven laskutusarkkitehtuuri: muutos siirtymällä Tarantooliin

[4] SWIM - klusterin rakentamisprotokolla

[5] GitHub - tarantool/patruuna-cli

[6] GitHub - tarantool/patruuna

Lähde: will.com

Lisää kommentti