OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

OpenResty: muudame NGINX tĂ€ielikuks rakenduste serveriksAvaldame taas konverentsi ettekande kokkuvĂ”tte HighLoad++ 2016, mis toimus Moskva oblastis Skolkovo 7–8 novembril möödunud aastal. Vladimir Protassov rÀÀgib, kuidas laiendada NGINX-i funktsionaalsust OpenResty ja Lua abil.

Tere kĂ”igile, minu nimi on Vladimir Protassov, töötan Parallelsis. RÀÀgin natuke endast. Oma elust kolm neljandikku olen kirjutanud koodi. Olen saanud programmi kirjutajaiks luude ja lihaste, isegi unes nĂ€en koodi. Üks neljandik elust on tööstuslik arendus, koodi kirjutamine, mis lĂ€heb otse tootmisse. Kood, mida mĂ”ned teist kasutavad, aga ei kahtlegi selles.

Ette mĂ”istaks, kui halb see kĂ”ik oli. Kui ma olin noor algaja, tulin ma siia ja mulle anti ĂŒle kaheterabaidised andmebaasid. NĂŒĂŒd on siin kĂ”igil highload. KĂ€isin konverentsidel ja kĂŒsisin: "Kuttid, rÀÀkige, teil on big data, kĂ”ik on lahe? Kui palju teil seal andmebaasi on?" Nad vastasid: "Meil on 100 gigabaiti!" Ma mĂ”tlesin: "Lahe, 100 gigabaiti!" Kuid samas mĂ”tlesin, kuidas oma nĂ€gu mitte reeta. Arvad, et jah, poisid on Ă€gedad, ja siis tuled tagasi ning tegeled nende mitme terabaidisete andmebaasidega. Ja see oli siis, kui olin algaja. Kas suudate ette kujutada, kui suur see ĆĄokk oli?

Ma oskan rohkem kui 20 programmeerimiskeelt. See on midagi, millega pidin töös tegelema. Sulle antakse kood Erlangis, C-s, C++-s, Luas, Pythoni, Ruby vÔi millegi muu peal, ja siis pead sa sellega kÔik hakkama saama. KokkuvÔttes tuli sellega tegeleda. TÀpselt arvestada ei Ônnestunud, aga number kadus kuskil 20 juurde.

Kuna kĂ”ik kohal viibijad teavad, mis on Parallels ja millega me tegeleme, ei hakka ma rÀÀkima, kui lahedad me oleme vĂ”i mida teeme. Ütlen ainult, et meil on 13 kontorit ĂŒlemaailmselt, ĂŒle 300 töötaja, arendus Moskvas, Tallinnas ja Maltal. Soovi korral vĂ”ib minna ja kolida Maltale, kui talvel on kĂŒlm ja on vaja sooja saada.

Konkreetne meie osakond kirjutab Python 2-ga. Me tegeleme Ă€ri kĂŒsimustega ja meil ei ole aega moetehnoloogiate rakendamiseks, seega kannatame. Meil on Django, sest see sisaldab kĂ”ike vajalikku, ning kĂ”ik liigne oleme vĂ€lja visanud. Samuti MySQL, Redis ja NGINX. Meil on ka palju muid huvitavaid asju. Meil on MongoDB, meil jooksevad kĂŒĂŒlikud, meil on kĂ”ik vĂ”imalik - aga see ei ole minu valdkond ja ma ei tegele sellega.

OpenResty

Oma kohta rÀÀkisin. Vaatame, millest ma tÀna rÀÀgin:

  • Mis on OpenResty ja milleks seda kasutatakse?
  • Miks leiutada veel ĂŒks ratta, kui meil on Python, NodeJS, PHP, Go ja muud vinged asjad, millega kĂ”ik rahul on?
  • Ja natuke elulisi nĂ€iteid. Mul tuli oma ettekannet tugevalt lĂŒhendada, sest see venis 3,5 tunniseks, seega nĂ€iteid jÀÀb vĂ€heks.

OpenResty — see NGINX. TĂ€nu sellele on meil tĂ€ielik veebiserver, mis on hĂ€sti kirjutatud ja töötab kiiresti. Arvan, et enamus meist kasutab NGINX-i tootmisreĆŸiimis. Te kĂ”ik teate, et see on kiire ja Ă€ge. Selles on tehtud suurepĂ€rane sĂŒnkroonne sisend/vĂ€ljund, seega ei pea me midagi leiutama nagu Pythonis, kus on leiutatud gevent. Gevent on Ă€ge, tĂ”eliselt hea, kuid kui kirjutate C koodi ja midagi lĂ€heb valesti, siis saate geventi debugeerides hulluks. Mul oli selline kogemus: vĂ”ttis lausa kaks pĂ€eva, et aru saada, mis tegelikult valesti lĂ€ks. Kui keegi poleks eelnevalt paar nĂ€dalat uurinud, probleemile jĂ€lile jĂ”udnud, Internetis kirjutama hakanud ning Google ei oleks seda leidnud, siis oleksime tĂ€ielikult hullu lĂ€inud.

NGINX sisaldab juba vahemĂ€lu ja staatilist sisu. Te ei pea muretsema, kuidas seda Ă”igesti teha, et see kuskil ei viivitu ja te ei kaotaks descriptor’e. Nginx'i seadistamine on vĂ€ga mugav, teil ei pea olema mures, mida valida - WSGI, PHP-FPM, Gunicorn vĂ”i Unicorn. Nginx on paigaldatud, adminnid saavad temaga hakkama, nad teavad, kuidas sellega töötada. Nginx töötleb pĂ€ringuid struktureeritult. RÀÀgin sellest veidi hiljem. LĂŒhidalt, sellel on faas, kus ta vĂ”tab vastuvaate, siis töötleb ja seejĂ€rel edastab sisu kasutajale.

Nginx on suurepĂ€rane, kuid ĂŒks probleem on: see ei ole piisavalt paindlik isegi kĂ”igi nende lahedate funktsioonide juures, mida on konfi sisse ehitatud. Sellest vĂ”imsusest jÀÀb puudu. SeetĂ”ttu integreerisid Taobao arendajad umbes seitse aastat tagasi sinna Lua. Mis see annab?

  • Suurus. See on vĂ€ike. LuaJIT pĂ”hjustab umbes 100-200 kilobaiti mĂ€lu ĂŒlekulu ja minimaalset jĂ”udluse ĂŒlekulu.
  • Kiirus. LuaJIT interpretator on paljuski sarnane C-le, mĂ”nel juhul kaotab Java'le ja mĂ”nel juhul aga juba saavutab samasuguseid tulemusi. Ühe perioodi jooksul peeti seda tipptasemel lahenduseks, parimaks JIT-kompileerijaks. NĂŒĂŒd on olemas paremusi, kuid need on vĂ€ga rasked, nĂ€iteks V8. MĂ”ned JavaScripti tĂ”lgendid ja Java HotSpot on mĂ”nes punktis kiirem, aga teistes kohtades jÀÀvad nad endiselt alla.
  • Lihtsus Ă”ppimisel. Kui teil on nĂ€iteks Perl-koodibaas ja te pole Booking, siis ei leia te Perl programmeerijaid. Sest neid pole, kĂ”ik on kadunud ja nende Ă”petamine vĂ”tab kaua aega. Kui soovite programmeerijaid mĂ”nel teisel platvormil, peate neid vĂ”ib-olla ka ĂŒmber Ă”petama vĂ”i leidma. Lua puhul on kĂ”ik lihtne. Lua on igale algajale kolme pĂ€evaga selge. Mul kulus umbes kaks tundi, et aru saada. Kahe tunni pĂ€rast juba kirjutasin tootmisfailidesse. Umbes nĂ€dala pĂ€rast lĂ€ks see tĂ”eliselt tootmisse.

Tulemuseks nÀeb see vÀlja nii:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Siin on palju asju. OpenResty on koondanud palju mooduleid, nii Lua mooduleid kui ka nginx mooduleid. KĂ”ik on valmis — laadi ĂŒles ja töötab.

NĂ€ited

Piisavalt luulest, liikuge koodi juurde. Siin on vÀike Hello World:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Mida siit leida vĂ”ib? See on NGINX'i asukoht. Me ei muretse, ei kirjuta oma marsruute, ei vĂ”ta mingit valmis varianti – meil on juba NGINX'is, me elame hĂ€sti ja laiskalt.

content_by_lua_block – see on plokk, mis ĂŒtleb, et anname sisu edasi Lua-skriptiga. VĂ”tame NGINX'i muutuja remote_addr ja sisestame selle string.format. See on sama, mis sprintf, ainult Lua's, ainult korrektne. Ja anname kliendile edasi.

Tulemuseks nÀeb see vÀlja nii:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Aga naaseme reaalsesse maailma. Tooteversioonile ei tĂ”steta ĂŒles Hello World'i. Meie rakendus kĂ€ib tavaliselt andmebaasi vĂ”i mujale ja veedab suure osa ajast vastust oodates.

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Lihtsalt istub ja ootab. See ei ole kÔige parem. Kui tuleb 100 000 kasutajat, on meil vÀga raske. Seega loome nÀitena lihtsa rakenduse. Otsime pilte, nÀiteks kasse. Kuid me ei otsi lihtsalt, vaid laiendame otsingusÔnu ja kui kasutaja otsib 'kutsikaid', siis leiame talle kasse, karvaseid ja muud. Esiteks peame saama taotluse andmed tagaplaanil. See nÀeb vÀlja nii:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Kaks rida vÔimaldavad sul hÔlpsasti GET-parameetreid hankida, mingeid komplikatsioone pole. Edasi saame nÀiteks andmebaasist vÔtme ja laiendi pÔhjal selle info tavalise SQL-pÀringuga. KÔik on lihtne. See nÀeb vÀlja selline:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Ühendame raamatukogu resty.mysql, mis meil juba komplektis on. Me ei pea midagi installima, kĂ”ik on valmis. NĂ€itame, kuidas ĂŒhenduda, ja teeme SQL-pĂ€ringu:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Siin on natuke hirmutav, kuid kĂ”ik töötab. Siin 10 – see on piirang. Me saame 10 rekordit, oleme laisad, ei taha rohkem nĂ€idata. SQL-is unustasin ma piirangust.

Edasi otsime pilte kÔigi pÀringute jaoks. Me kogume hulga pÀringuid ja tÀidame Lua-tabeli, mis kannab nime reqs, ja teeme ngx.location.capture_multi.

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

KÔik need pÀringud saadetakse paralleelselt, ja me saame vastused tagasi. Tööaeg on vÔrdsustatud kÔige aeglasema vastuse ajaga. Kui kÔik lÀhevad vÀlja 50 millisekundi jooksul ja me saatsime sada pÀringut, siis saab vastus meieni 50 millisekundi jooksul.

Kuna me oleme laisad ja ei taha kirjutada HTTP töötlemist ja vahemÀlu, paneme NGINX-i meie eest kÔike tegema. Kuidas nÀgite, seal oli pÀring url/fetch, see ongi:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Teeme lihtsa proxy_pass, me seame, kuhu vahemÀlu salvestada, kuidas seda teha, ja meil on kÔik töötab.

Aga sellest ei piisa, me peame veel andmed kasutajale edastama. Lihtsaim mÔte on kÔik seriseerida JSON formaati, lihtsalt, kahel real. Edastame Content-Type, edastame JSON.

Aga on ĂŒks keerukus: kasutaja ei taha JSONi lugeda. Tuleb meelitada frontend-arendajaid. MĂ”nikord ei taha me seda kohe teha. Ja SEO spetsialistid ĂŒtlevad, et kui me otsime pilte, siis see ei ole nende jaoks oluline. Aga kui me anname neile mingit sisu, siis nad ĂŒtlevad, et meie otsijad ei indekseeri midagi.

Mida sellega teha? Loomulikult anname kasutajale HTMLi. KĂ€sitsi genereerimine ei ole mugav, seega tahame kasutada malli. Selleks on olemas teek lua-resty-template.

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Te olete ilmselt nÀinud kolme kohutavat tÀhte OPM. OpenResty tuleb koos oma paketihalduriga, kust saab paigaldada veel hulk erinevaid mooduleid, sealhulgas lua-resty-template. See on lihtne mallimootor, mis on sarnane Django mallidele. Seal saab kirjutada koodi ja teha muutujate asendusi.

KokkuvÔttes nÀeb kÔik vÀlja umbes nii:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Me kogusime andmed ja genereerisime malli taas kahe reana. Kasutaja on rahul, sai kassipojad. Kuna me laiendasime pĂ€ringut, sai ta kassipoegade lisaks ka merikassi. Kes teab, vĂ”ib-olla otsis ta just seda, kuid ei osanud kĂŒsida.

KÔik on suurepÀrane, aga me oleme ju arenduses ega soovi veel kasutajatele nÀidata. Teeme autentimise. Selleks vaatame, kuidas NGINX kÀsitleb pÀringut OpenResty mÔistes:

  • Esimene faas — access, kui kasutaja alles saabus ja me vaatasime teda pĂ€iste, IP-aadressi ja muude andmete jĂ€rgi. Saame kohe vĂ€lja lĂŒlitada, kui ta meile ei meeldi. Seda saab kasutada autentimiseks vĂ”i kui me saame vĂ€ga palju pĂ€ringuid, saame neid kergesti selles faasis katkestada.
  • rewrite. Kirjutame mĂ”ningaid pĂ€ringu andmeid ĂŒmber.
  • content. Anname kasutajale sisu.
  • headers filter. Asendame vastuse pĂ€iseid. Kui oleme kasutanud proxy_pass, saame mĂ”ningaid pĂ€iseid ĂŒle kirjutada enne, kui kasutajale edastame.
  • body filter. Saame keha asendada.
  • log — logimine. Saame kirjutada logisid elasticsearchi ilma tĂ€iendava kihita.

Meie autentimise protsess nÀeb vÀlja umbes nii:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Lisame selle asukohta, mille me eelnevalt kirjeldasime, ja paneme sinna jÀrgmise koodi:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Kontrollime, kas meil on cookie token. Kui ei ole, suuname autentimisele. Kasutajad on leidlikud ja vÔivad aimata, et tuleb seada cookie token. SeetÔttu salvestame selle ka Redis-sse:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Kood Redis-i kasutamiseks on vĂ€ga lihtne ja ei erine teistest keeltest. KĂ”ik sisend/vĂ€ljastus seal ja siin ei ole blokeeriv. Kui kirjutate sĂŒnkroonselt, töötab see asĂŒnkroonselt. Umbes nagu gevent, ainult et hĂ€sti teostatud.

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Teeme nĂŒĂŒd autentimise:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Ütleme, et meil on vaja lugeda pĂ€ringu keha. Saame POST-argumendid, kontrollime, et kasutajanimi ja parool on Ă”iged. Kui need on vale, suuname autentimisele. Kui need on Ă”iged, salvestame tokeni Redis-sse:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

Ärge unustage seada cookie-it, see tehakse ka kahe reaga:

OpenResty: muudame NGINX tÀielikuks rakenduste serveriks

NÀide on lihtne ja teoreetiline. Me ei plaani teenust, mis nÀitab inimestele kasside fotosid. Kuigi kes teab. SeetÔttu vaatame, mida saame tootmises teha.

  • Minimalistlik tagaplaan. Aeg-ajalt on meil vaja backend'ile anda vaid natuke andmeid: kuskil tuleb kuupĂ€ev sisestada, kuskil peab mingi nimekiri vĂ€lja tooma, öelda, kui palju kasutajaid on praegu saidil, kinnitada loendur vĂ”i statistika. Midagi niisugust. VĂ€iksemaid tĂŒkke on vĂ€ga lihtne teha. Nii saab kiiresti, lihtsalt ja suurepĂ€raselt hakkama.
  • Andmete eeltöötlemine. Aeg-ajalt soovime oma lehekĂŒljele reklaami lisada, ja seda reklaami me vĂ”tame API-pĂ€ringutega. Sellist on siinkohal vĂ€ga lihtne teha. Me ei koorma oma backend'it, mis juba niigi raskelt töötab. Saame seda lihtsalt kokku panna. Saame luua mĂ”ningaid JS-e vĂ”i vastupidi, lahti vĂ”tta, midagi eeltöötleda enne, kui kasutajale edastame.
  • Mikroteenuse fassaad. See on samuti vĂ€ga hea juhtum, mille ma ise ellu viisin. Enne seda töötasin firmas Tenzor, mis tegeleb elektroonilise arvestuse ja tagab aruandluse umbes poolele juriidilistele isikutele riigis. Meie lĂ”ime teenuse, kus selle sama mehhanismi abil on tehtud palju asju: marsruutimine, autoriseerimine ja muu.
    OpenResty on ideaalne liim teie mikroteenuste jaoks, pakkudes ĂŒhtset juurdepÀÀsu ja liidest. Kuna mikroteenused vĂ”ivad olla kirjutatud erinevates keeltes, nagu Node.js, PHP, Python ja isegi Erlang, soovime vĂ€ltida koodi korduvat kirjutamist erinevates kohtades. SeetĂ”ttu saab OpenResty paigutada esikĂŒljele.
  • Statistika ja analĂŒĂŒtika. Üldiselt töötab NGINX sisendisse, ja kĂ”ik pĂ€ringud lĂ€hevad selle kaudu. Just siin on mugav kokku koguda. Saame kohe midagi arvutada ja saata nĂ€iteks Elasticsearchi, Logstashi vĂ”i lihtsalt salvestada logisse ja hiljem mujale edastada.
  • Mitme kasutaja sĂŒsteemid. NĂ€iteks online-mĂ€ngude loomine on samuti vĂ€ga tĂ”hus. TĂ€na Cape Townis rÀÀgib Alexander Gladish, kuidas kiiresti prototĂŒĂŒpida mitme kasutajaga mĂ€ngu OpenRestyi abil.
  • PĂ€ringute filtreerimine (WAF). Praegu on moes kasutada erinevaid veebirakenduste tulemĂŒĂŒre, neid pakuvad mitmed teenused. OpenResty abil saate luua enda veebirakenduste tulemĂŒĂŒri, mis filtreerib pĂ€ringud teie nĂ”udmiste jĂ€rgi lihtsalt ja mugavalt. Kui teil on Python, siis mĂ”istate, et PHP ei saa kindlasti manustada, kui te seda konsoolis kuskil ei esitata. Te teate, et teil on MySQL ja Python. TĂ”enĂ€oliselt vĂ”idakse siin proovida mĂ”nda katalogiĂŒleminekut ja midagi andmebaasi manustada. SeetĂ”ttu saab kahtlased pĂ€ringud kiiresti ja odavalt filtreerida otse eesliinil.
  • Ühendus. Kuna OpenResty pĂ”hineb NGINX-il, siis on tal eelis — see NGINX-i kogukond. See on vĂ€ga suur ning suurem osa kĂŒsimusi, mis vĂ”ivad teil alguses tekkida, on juba NGINX-i kogukonna poolt lahendatud.

    Lua-arendajad. Eile rÀÀkisin kolleegidega, kes osalesid HighLoad++ Ă”ppepĂ€eval, ja kuulsin, et ainult Tarantool on kirjutatud Lua-s. See ei ole tĂ”si, Lua-s on palju rohkem asju. NĂ€iteks: OpenResty, XMPP-server Prosody, mĂ€ngumootor Love2D, Lua scriptide kirjutamine Warcraftis ja mujal. Lua arendajaid on palju, nende kogukond on suur ja abivalmis. KĂ”ik mu kĂŒsimused Lua kohta lahendati mĂ”ne tunni jooksul. Kui kirjutan postitusloendisse, saab juba mĂ”ne minutiga hulgaliselt vastuseid, kus seletatakse, mis ja kuidas. See on tĂ”eliselt suur asi. Kahjuks ei ole igal pool nii sooja ja avatud kogukonda.
    OpenResty kohta on GitHub, seal saab avada issue, kui midagi katki lĂ€heb. On olemas postitusloend Google Groups'is, kus saab arutada ĂŒldisi kĂŒsimusi, ja on ka hiinakeelne postitusloend — vĂ”ib-olla ei valda te inglise keelt, aga hiina keel on tuttav.

KokkuvÔte

  • Loodan, et suutsin edastada, et OpenResty on vĂ€ga mugav raamistik, mis on loodud veebi jaoks.
  • Sellel on madal sissejuhatuse kĂŒnnis, kuna kood sarnaneb sellega, millega me kirjutame, keel on ĂŒsna lihtne ja minimalistik.
  • See pakub asĂŒnkroonset I/O ilma callback'ideta, meil ei ole hĂ”lpu, nagu me mĂ”nikord kirjutame NodeJS-is.
  • Tegutseme kiiresti, kuna vajame ainult NGINX-i koos vajaliku mooduliga ja meie koodi ning kĂ”ik töötab kohe.
  • Suur ja aktiivne kogukond.

Ma ei ole ĂŒksikasjalikult selgitanud, kuidas marsruutimine toimub; see osutus liiga pikaks jutuks.

AitÀh tÀhelepanu eest!

Vaata videot

Vladimir Protasov — OpenResty: muudame NGINX-i tĂ€ielikuks rakenduste serveriks

Allikas: habr.com
Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid đŸ”„ Osta usaldusvÀÀrne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster