OpenResty: premena NGINX na plnohodnotný aplikačný server

OpenResty: premena NGINX na plnohodnotný aplikačný serverOpäť zverejňujeme prepis správy z konferencie HighLoad++ 2016, ktorý sa konal v Skolkove pri Moskve v dňoch 7. – 8. novembra minulého roku. Vladimír Protasov vysvetľuje, ako rozšíriť funkčnosť NGINX pomocou OpenResty a Lua.

Ahojte všetci, volám sa Vladimir Protasov, pracujem v Parallels. Poviem vám niečo o sebe. Tri štvrtiny svojho života strávim písaním kódu. Stal som sa programátorom až do špiku kostí v doslovnom zmysle: niekedy vidím kód vo svojich snoch. Štvrtina života je priemyselný rozvoj, písanie kódu, ktorý ide priamo do výroby. Kód, ktorý niektorí z vás používajú, ale neuvedomujú si to.

Takže chápete, aké to bolo zlé. Keď som bol malý, prišiel som a dostal som tieto dvojterabajtové databázy. Teraz je tu pre všetkých vysoká záťaž. Chodil som na konferencie a pýtal som sa: „Chlapci, povedzte mi, máte veľké dáta, je všetko v pohode? Koľko základov tam máte? Odpovedali mi: "Máme 100 gigabajtov!" Povedal som: "Super, 100 gigabajtov!" A premýšľal som, ako si starostlivo udržiavať poker face. Myslíte si, že áno, chlapci sú v pohode, a potom sa vrátite a budete sa pohrávať s týmito multiterabajtovými databázami. A toto je byť juniorom. Viete si predstaviť, aká je to rana?

Ovládam viac ako 20 programovacích jazykov. Toto je niečo, čo som musel zistiť, keď som pracoval. Dajú vám kód v Erlang, C, C++, Lua, Python, Ruby, niečo iné a vy to všetko musíte orezať. Vo všeobecnosti som musel. Nedalo sa vypočítať presné číslo, ale niekde okolo 20. sa číslo stratilo.

Keďže každý prítomný vie, čo je Parallels a čo robíme, nebudem hovoriť o tom, akí sme cool a čo robíme. Poviem vám, že máme 13 kancelárií po celom svete, viac ako 300 zamestnancov, vývoj v Moskve, Talline a na Malte. Ak chcete, môžete si ho vziať a presťahovať sa na Maltu, ak je v zime zima a potrebujete si zahriať chrbát.

Konkrétne naše oddelenie píše v Pythone 2. Podnikáme a nemáme čas implementovať módne technológie, takže trpíme. Používame Django, pretože má všetko, a čo bolo zbytočné, sme zobrali a vyhodili. Tiež MySQL, Redis a NGINX. Máme aj veľa iných super vecí. Máme MongoDB, okolo nás behajú králiky, máme všetko – ale nie je to moje a ja to nerobím.

OpenResty

Povedal som o sebe. Poďme zistiť, o čom budem dnes hovoriť:

  • Čo je OpenResty a s čím sa jedáva?
  • Prečo znovu vymýšľať ďalšie koleso, keď máme Python, NodeJS, PHP, Go a ďalšie skvelé veci, s ktorými sú všetci spokojní?
  • A pár príkladov zo života. Report som musel veľmi zostrihať, pretože mi to trvalo 3,5 hodiny, takže príkladov bude málo.

OpenResty je NGINX. Vďaka nemu máme plnohodnotný web server, ktorý je dobre napísaný a funguje rýchlo. Myslím, že väčšina z nás používa pri výrobe NGINX. Všetci viete, že je rýchly a cool. Urobili v ňom skvelé synchrónne I/O, takže nemusíme nič cyklovať, rovnako ako to urobili v Pythone. Gevent je super, super, ale ak napíšete C kód a niečo sa pokazí, tak s Geventom sa zbláznite do ladenia. Mal som skúsenosť: trvalo dva celé dni, kým som zistil, čo sa tam pokazilo. Ak by sa niekto niekoľko týždňov nehrabal, nenašiel problém, nenapísal na internet a Google by ho nenašiel, tak by sme sa úplne zbláznili.

NGINX už má ukladanie do vyrovnávacej pamäte a statický obsah hotové. Netreba si lámať hlavu nad tým, ako to urobiť ľudsky, aby ste niekde nespomalili, aby ste niekde nestratili deskriptory. Nginx je veľmi pohodlný na nasadenie, nemusíte premýšľať o tom, čo si vziať - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx bol nainštalovaný, odovzdaný správcom, vedia s ním pracovať. Nginx spracováva požiadavky štruktúrovaným spôsobom. Budem o tom hovoriť trochu neskôr. Má skrátka fázu, kedy požiadavku len prijal, kedy ju spracoval a kedy naservíroval obsah užívateľovi.

Nginx je v pohode, ale je tu jeden problém: nie je dostatočne flexibilný, dokonca aj so všetkými skvelými funkciami, ktoré chlapci napchali do konfigurácie, napriek tomu, čo sa dá nakonfigurovať. Táto sila nestačí. Preto chlapci z Taobao, dávno, zdá sa, že pred ôsmimi rokmi, do toho zabudovali Luu. čo to dáva?

  • Veľkosť. Je to malé. LuaJIT poskytuje približne 100-200 kilobajtov réžie pamäte a minimálnu réžiu výkonu.
  • Rýchlosť. Interpret LuaJIT má v mnohých situáciách blízko k C, v niektorých situáciách s Javou prehráva, v iných ju prekonáva. Nejaký čas bol považovaný za najmodernejší kompilátor JIT. Teraz existujú chladnejšie, ale sú veľmi ťažké, napríklad rovnaký V8. Niektorí interpreti JS a Java HotSpot sú v niektorých bodoch rýchlejší, no na niektorých miestach stále strácajú.
  • Ľahko sa učí. Ak máte, povedzme, základňu kódu Perl a nie ste Booking, nenájdete programátorov Perl. Pretože neexistujú, boli všetci odobratí a učiť ich je dlhé a ťažké. Ak chcete programátorov na niečo iné, možno ich budete musieť preškoliť alebo nájsť. V prípade Lua je všetko jednoduché. Každý junior sa môže naučiť Lua za tri dni. Trvalo mi asi dve hodiny, kým som na to prišiel. O dve hodiny neskôr som už písal kód vo výrobe. Asi o týždeň išiel rovno do výroby a odišiel.

Vo výsledku to vyzerá takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Je tu toho veľa. OpenResty zhromaždil veľa modulov, luash aj motor. A všetko máte pripravené – nasadené a fungujúce.

príklady

Dosť bolo textov, prejdime ku kódu. Tu je malý Hello World:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Čo je tam? Toto je lokalita Engins. Netrápime sa, nepíšeme si vlastné smerovanie, neberieme žiadne hotové – už to máme v NGINX, žijeme dobrý a lenivý život.

content_by_lua_block je blok, ktorý hovorí, že obsah poskytujeme pomocou skriptu Lua. Vezmeme premennú Engins remote_addr a vložte ho string.format. Je to rovnaké ako sprintf, len v Lua, len správne. A my to dávame klientovi.

Vo výsledku to bude vyzerať takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Vráťme sa však do reálneho sveta. Hello World do výroby nikto nenasadí. Naša aplikácia väčšinou ide do databázy alebo niekde inde a väčšinou čaká na odpoveď.

OpenResty: premena NGINX na plnohodnotný aplikačný server

Len sedí a čaká. Nie je to veľmi dobré. Keď príde 100.000 XNUMX používateľov, je to pre nás veľmi ťažké. Použime teda ako príklad jednoduchú aplikáciu. Budeme hľadať obrázky napríklad mačiek. Nebudeme však len hľadať, rozšírime kľúčové slová a ak používateľ hľadal „mačiatka“, nájdeme mačky, chlpaté mačky atď. Najprv musíme získať údaje o požiadavke na backend. Vyzerá to takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Dva riadky umožňujú bez komplikácií vyzdvihnúť parametre GET. Ďalej, povedzme, z databázy so znakom pre kľúčové slovo a rozšírenie získame tieto informácie pomocou bežného SQL dotazu. Je to jednoduché. Vyzerá to takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Pripojenie knižnice resty.mysql, ktoré už máme v súprave. Nemusíme nič inštalovať, všetko je pripravené. Uvádzame, ako sa pripojiť a vytvoriť SQL dotaz:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Je to tu trochu strašidelné, ale všetko funguje. Tu je limit 10. Vyťahujeme 10 záznamov, sme leniví, viac sa nám nechce ukázať. Zabudol som na limit v SQL.

Ďalej nájdeme obrázky pre všetky otázky. Zhromažďujeme množstvo žiadostí a vypĺňame tabuľku Lua s názvom reqsa my áno ngx.location.capture_multi.

OpenResty: premena NGINX na plnohodnotný aplikačný server

Všetky tieto požiadavky sa posielajú paralelne a odpovede sa nám vracajú. Prevádzkový čas sa rovná času odozvy najpomalšieho z nich. Ak všetci vystrelíme za 50 milisekúnd a odošleme sto žiadostí, odpoveď dostaneme za 50 milisekúnd.

Keďže sme leniví a nechce sa nám písať HTTP a spracovanie vyrovnávacej pamäte, prinútime NGINX, aby urobil všetko za nás. Ako ste videli, bola tu žiadosť o url/fetch, tu je:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Robíme to jednoduché proxy_pass, naznačíme, kde uložiť do vyrovnávacej pamäte, ako to urobiť a všetko nám funguje.

To však nestačí, údaje ešte musíme poskytnúť používateľovi. Najjednoduchším nápadom je serializovať všetko v JSON, jednoducho, v dvoch riadkoch. Dáme Content-Type, dáme JSON.

Je tu však jeden problém: používateľ nechce čítať JSON. Musíme prilákať front-end vývojárov. Niekedy sa nám to spočiatku nechce. A SEO špecialisti povedia, že ak hľadáme obrázky, potom im na tom nezáleží. A ak im dáme nejaký obsah, povedia, že naše vyhľadávače nič neindexujú.

Čo s tým robiť? Samozrejme, dáme používateľovi HTML. Ručné generovanie nie je comme il faut, preto chceme použiť šablóny. Na to existuje knižnica lua-resty-template.

OpenResty: premena NGINX na plnohodnotný aplikačný server

Pravdepodobne ste už videli tri strašidelné písmená OPM. OpenResty prichádza s vlastným správcom balíkov, prostredníctvom ktorého si môžete nainštalovať množstvo rôznych modulov, najmä lua-resty-template. Toto je jednoduchý nástroj šablón, podobný šablónam Django. Tam môžete písať kód a vykonávať premennú substitúciu.

V dôsledku toho bude všetko vyzerať takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Zobrali sme údaje a vykreslili šablónu, opäť v dvoch riadkoch. Užívateľ je spokojný, dostal mačky. Keďže sme požiadavku rozšírili, dostal aj kožušinovú pečať pre mačiatka. Nikdy neviete, možno práve toto hľadal, no nedokázal svoju požiadavku správne sformulovať.

Všetko je v poriadku, ale sme vo vývoji a ešte to nechceme ukazovať používateľom. Urobme autorizáciu. Aby sme to urobili, pozrime sa, ako NGINX spracováva požiadavku v podmienkach OpenResty:

  • Prvá fáza - prístup, keď používateľ práve prišiel, a pozreli sme sa na neho podľa hlavičiek, IP adresy a ďalších údajov. Ak sa nám to nepáči, môžeme to okamžite prerušiť. To sa dá použiť na autorizáciu, alebo ak dostaneme veľa požiadaviek, môžeme ich v tejto fáze jednoducho odrezať.
  • prepísať. Prepisujeme niektoré údaje žiadosti.
  • obsah. Obsah doručujeme používateľovi.
  • filter hlavičiek. Nahrádzame hlavičky odpovedí. Ak sme použili proxy_pass, môžeme prepísať niektoré hlavičky predtým, ako ich dáme používateľovi.
  • telesný filter. Môžeme zmeniť telo.
  • záznam — ťažba dreva. Logy môžete písať v elasticsearch bez ďalšej vrstvy.

Naša autorizácia bude vyzerať asi takto:

OpenResty: premena NGINX na plnohodnotný aplikačný server

K tomu pridáme toto location, ktorý sme opísali predtým, a vložte tam nasledujúci kód:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Pozeráme sa, či máme token cookie. Ak nie, požiadame o autorizáciu. Používatelia sú prefíkaní a vedia odhadnúť, že potrebujú nastaviť token súboru cookie. Preto to dáme aj do Redis:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Kód pre prácu s Redis je veľmi jednoduchý a nelíši sa od iných jazykov. Zároveň tu a tam nie je blokovaný všetok vstup/výstup. Ak napíšete synchrónny kód, funguje asynchrónne. Takmer ako gevent, ale dobre urobené.

OpenResty: premena NGINX na plnohodnotný aplikačný server

Urobme samotnú autorizáciu:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Hovoríme, že si musíme prečítať telo žiadosti. Dostávame argumenty POST a kontrolujeme, či sú prihlasovacie meno a heslo správne. Ak sú nesprávne, požiadame vás o autorizáciu. A ak je to správne, napíšte token do Redis:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Nezabudnite nastaviť cookie, to sa tiež robí v dvoch riadkoch:

OpenResty: premena NGINX na plnohodnotný aplikačný server

Príklad je jednoduchý a špekulatívny. Samozrejme, neurobíme službu, ktorá ľuďom ukazuje mačky. Ale kto nás pozná. Poďme si teda prejsť, čo sa dá robiť vo výrobe.

  • Minimalistický backend. Niekedy potrebujeme do backendu vypísať len málo údajov: niekde musíme vložiť dátum, niekde zobraziť zoznam, povedať, koľko používateľov je práve na stránke, pripojiť počítadlo alebo štatistiku. Niečo také malé. Niektoré minimálne kúsky sa dajú vyrobiť veľmi jednoducho. Vďaka tomu to bude rýchle, jednoduché a skvelé.
  • Predspracovanie údajov. Niekedy chceme na našu stránku vložiť reklamu a túto reklamu dostávame pomocou žiadostí API. Tu je to veľmi jednoduché. Nezaťažujeme náš backend, ktorý už sedí a tvrdo pracuje. Tu si ho môžete vyzdvihnúť a zozbierať. Môžeme dať dokopy nejaký JS alebo ho naopak odpojiť a niečo predspracovať predtým, ako to dáme používateľovi.
  • Fasáda pre mikroservis. Toto je tiež veľmi dobrý prípad, implementoval som ho. Predtým som pracoval v spoločnosti Tenzor, ktorá sa zaoberá elektronickým reportingom a poskytuje reporting približne polovici právnických osôb v krajine. Vytvorili sme službu, veľa vecí sa tam urobilo pomocou rovnakého mechanizmu: smerovanie, autorizácia a ďalšie.
    OpenResty možno použiť ako lepidlo pre vaše mikroslužby, ktoré poskytujú jediný prístup ku všetkému a jediné rozhranie. Keďže mikroslužby môžu byť napísané tak, že tu máte Node.js, tu PHP, tu Python, tu niečo s Erlangom, chápeme, že nechceme všade prepisovať rovnaký kód. Preto je možné OpenResty zapojiť do prednej časti.

  • Štatistika a analytika. NGINX je zvyčajne pri vchode a všetky požiadavky prechádzajú cez ňu. Práve na tomto mieste je veľmi výhodné zbierať. Môžete okamžite niečo vypočítať a niekam nahrať, napríklad Elasticsearch, Logstash, alebo to jednoducho zapísať do logu a potom niekam poslať.
  • Systémy pre viacerých používateľov. Veľmi dobré sú napríklad aj online hry. Alexander Gladysh dnes v Kapskom Meste porozpráva o tom, ako rýchlo prototypovať hru pre viacerých hráčov pomocou OpenResty.
  • Filtrovanie požiadaviek (WAF). V súčasnosti je v móde vyrábať všetky druhy firewallov webových aplikácií, existuje veľa služieb, ktoré ich poskytujú. Pomocou OpenResty si môžete vytvoriť firewall webovej aplikácie, ktorý bude jednoducho a jednoducho filtrovať požiadavky podľa vašich požiadaviek. Ak máte Python, tak chápete, že PHP sa do vás určite nenapichne, pokiaľ ho samozrejme nespawnujete kdekoľvek z konzoly. Viete, že máte MySQL a Python. Pravdepodobne by sa mohli pokúsiť urobiť nejaký druh prechodu cez adresár a vložiť niečo do databázy. Preto môžete odfiltrovať podivné otázky rýchlo a lacno hneď vpredu.
  • Spoločenstva. Keďže OpenResty je postavené na NGINX, má bonus – toto komunita NGINX. Je veľmi rozsiahly a slušnú časť otázok, ktoré budete mať na začiatku, už komunita NGINX vyriešila.

    Lua vývojári. Včera som sa rozprával s chalanmi, ktorí prišli na tréningový deň HighLoad++ a počuli, že iba Tarantool je napísaný v Lua. To nie je pravda, veľa vecí je napísaných v Lua. Príklady: OpenResty, server Prosody XMPP, herný engine Love2D, skript Lua vo Warcrafte a inde. Vývojárov Lua je veľa, majú veľkú a pohotovú komunitu. Všetky moje Lua otázky boli vyriešené v priebehu niekoľkých hodín. Keď napíšete do mailing listu, doslova v priebehu niekoľkých minút už máte kopu odpovedí, ktoré popisujú čo a ako, čo je čo. Je to skvelé. Žiaľ, takéto milé, duchovné spoločenstvo nie je všade.
    Existuje GitHub pre OpenResty, kde môžete otvoriť problém, ak sa niečo pokazí. V Skupinách Google je zoznam adresátov, kde môžete diskutovať o všeobecných problémoch, existuje zoznam adresátov v čínštine - nikdy neviete, možno nehovoríte po anglicky, ale viete po čínsky.

Výsledky

  • Dúfam, že sa mi podarilo vyjadriť, že OpenResty je veľmi pohodlný rámec prispôsobený pre web.
  • Má nízku bariéru vstupu, keďže kód je podobný tomu, v ktorom píšeme, jazyk je pomerne jednoduchý a minimalistický.
  • Poskytuje asynchrónne I/O bez spätných volaní, nebudeme mať žiadne rezance, aké môžeme niekedy písať v NodeJS.
  • Má jednoduché nasadenie, keďže nám stačí NGINX s potrebným modulom a naším kódom a všetko funguje hneď.
  • Veľká a citlivá komunita.

Nepovedal som podrobne, ako sa robí smerovanie, ukázalo sa, že je to veľmi dlhý príbeh.

Ďakujem vám za pozornosť!


Vladimir Protasov - OpenResty: premena NGINX na plnohodnotný aplikačný server

Zdroj: hab.com

Pridať komentár