OpenResty: förvandlar NGINX till en komplett applikationsserver

OpenResty: förvandlar NGINX till en komplett applikationsserverVi publicerar Ă„terigen en transkription av föredraget frĂ„n konferensen HighLoad++ 2016, som hölls i Skolkovo i Moskva-regionen den 7–8 november förra Ă„ret. Vladimir Protasov berĂ€ttar hur man utökar funktionaliteten av NGINX med OpenResty och Lua.

Hej alla, jag heter Vladimir Protasov, jag arbetar pÄ Parallels. Jag ska berÀtta lite om mig sjÀlv. I tre fjÀrdedelar av mitt liv har jag Àgnat mig Ät att skriva kod. Jag blev programmerare Ànda in i sjÀlen, bokstavligen: ibland drömmer jag om kod. En fjÀrdedel av livet handlar om industriell utveckling, att skriva kod som gÄr direkt till produktion. Koden som vissa av er anvÀnder, men inte misstÀnker.

För att ni ska förstÄ hur illa det var. NÀr jag var en liten junior kom jag in och fick sÄdana tvÄterabyte databaser. Nu har alla highload hÀr. Jag gick pÄ konferenser och frÄgade: "Tja, berÀtta, har ni big data, Àr allt coolt? Hur stora databaser har ni?" De svarade: "Vi har 100 gigabyte!" Jag sa: "Coolt, 100 gigabyte!" Men tÀnkte för mig sjÀlv, hur jag skulle hÄlla en pokerface. Du tÀnker, ja, de Àr coola, och sen kommer du tillbaka och grÀver med dessa multiterabyte databaser. Och detta - nÀr jag var junior. Kan ni förestÀlla er hur hÄrt det var?

Jag kan mer Àn 20 programmeringssprÄk. Det Àr nÄgot jag har fÄtt lÀra mig under arbetets gÄng. Du fÄr kod pÄ Erlang, C, C++, Lua, Python, Ruby och nÄgot annat, och du mÄste arbeta med allt det. SÄ det blev sÄ. Jag har inte lyckats rÀkna det exakta antalet, men det förlorade jag mig nÄgonstans kring 20.

Eftersom alla nÀrvarande vet vad Parallels Àr och vad vi gör, kommer jag inte att prata om hur coola vi Àr och vad vi gör. Jag berÀttar bara att vi har 13 kontor runt om i vÀrlden, över 300 anstÀllda, utveckling i Moskva, Tallinn och Malta. Om sÄ önskas kan man faktiskt flytta till Malta om det Àr kallt pÄ vintern och man behöver vÀrma ryggen.

Specifikt vÄr avdelning skriver i Python 2. Vi sysslar med affÀrer och har inte tid att införa trendiga teknologier, sÄ vi lider. Vi har Django, för i den finns allt, och det överflödiga har vi tagit bort. Dessutom MySQL, Redis och NGINX. Vi har ocksÄ mÄnga andra coola saker. Vi har MongoDB, vÄra kaniner springer omkring, vi har sÄ mycket olika grejer - men det Àr inte mitt omrÄde, och jag sysslar inte med det.

OpenResty

Jag har berÀttat om mig sjÀlv. LÄt oss ta reda pÄ vad jag ska prata om idag:

  • Vad Ă€r OpenResty och hur anvĂ€nds det?
  • Varför uppfinna Ă€nnu en cykel nĂ€r vi har Python, NodeJS, PHP, Go och andra fantastiska saker som alla Ă€r nöjda med?
  • Och lite exempel frĂ„n verkligheten. Jag var tvungen att kraftigt korta ned min presentation eftersom den blev 3,5 timmar lĂ„ng, sĂ„ det blir fĂ„ exempel.

OpenResty Àr NGINX. Tack vare det har vi en fullt fungerande webbserver som Àr vÀlskriven och snabb. Jag tror att de flesta av oss anvÀnder NGINX i produktion. Alla vet att den Àr snabb och bra. Den har en fantastisk synkron in-/utmatning, sÄ vi behöver inte hitta pÄ nÄgot nytt som vi gjorde i Python med gevent. Gevent Àr fantastiskt, men om du skriver C-kod och nÄgot gÄr fel, kommer du att bli galen av att debugga det med gevent. Jag hade den erfarenheten: det tog mig tvÄ hela dagar att förstÄ vad som gÄtt fel. Om ingen hade grÀvt i det i flera veckor, hittat problemet, skrivit om det pÄ internet, och Google inte hade funnit det, skulle vi ha blivit helt galna.

I NGINX finns redan caching och statiskt innehĂ„ll. Du behöver inte oroa dig för hur man gör det pĂ„ ett korrekt sĂ€tt sĂ„ att det inte saktar ner nĂ„gonstans, eller att du tappar nĂ„gra deskriptorer. NGINX Ă€r vĂ€ldigt enkelt att distribuera, du behöver inte tĂ€nka pĂ„ vad du ska vĂ€lja – WSGI, PHP-FPM, Gunicorn, Unicorn. NGINX installeras, adminerna tar hand om det, och de vet hur man arbetar med det. NGINX strukturerat hanterar förfrĂ„gningar. Jag kommer att berĂ€tta lite mer om det senare. Kort sagt, det finns en fas nĂ€r den just har tagit emot förfrĂ„gan, nĂ€r den har behandlat den och nĂ€r den har returnerat innehĂ„llet till anvĂ€ndaren.

NGINX Àr bra, men det finns ett problem: det Àr inte tillrÀckligt flexibelt, Àven med alla de fantastiska funktionerna som utvecklarna har lagt in i konfigurationen. Denna kraft rÀcker inte till. DÀrför integrerade teamet frÄn Taobao för lÀnge sedan, verkar det vara för Ätta Är sedan, Lua i det. Vad ger det?

  • Dimensions. Det Ă€r litet. LuaJIT ger ungefĂ€r 100-200 kilobyte overhead i minnet och minimal overhead i prestanda.
  • Hastighet. LuaJIT-tolkaren Ă€r i mĂ„nga situationer nĂ€ra C, i vissa situationer slĂ„r det Java, i andra Ă€r det snabbare Ă€n den. Under en tid ansĂ„gs det vara den mest avancerade JIT-kompilatorn. Numera finns det mer avancerade, men de Ă€r mycket tyngre, som till exempel V8. Vissa JS-tolkare och Java HotSpot Ă€r snabbare i vissa aspekter, men i andra omrĂ„den förlorar de fortfarande.
  • AnvĂ€ndarvĂ€nlighet. Om du till exempel har en kodbas i Perl, och du inte Ă€r Booking, kommer du inte att hitta Perl-programmerare. För de finns inte, de har alla blivit upptagna, och att lĂ€ra dem tar tid och Ă€r svĂ„rt. Om du vill ha programmerare i nĂ„got annat sprĂ„k, kanske du ocksĂ„ behöver omskola dem, eller sĂ„ fĂ„r du leta. För Lua Ă€r det enkelt. Lua kan lĂ€ras av vilken junior som helst pĂ„ tre dagar. Jag behövde ungefĂ€r tvĂ„ timmar för att förstĂ„ det. Efter tvĂ„ timmar skrev jag redan kod i produktionen. UngefĂ€r en vecka senare var den direkt i produktionen.

Resultatet ser ut sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Det finns mycket hĂ€r. I OpenResty har de samlat en massa moduler, bĂ„de Lua och NGINX-specifika. Och allt Ă€r klart – bara dyk in och det fungerar.

Exempel

Nog med poesi, let's gÄ till koden. HÀr Àr en liten Hello World:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vad finns hĂ€r? Det Ă€r en NGINX-location. Vi grĂ€mer oss inte, vi skriver ingen egen routing, vi tar ingen fĂ€rdig – vi har redan det i NGINX, vi lever bra och lat.

content_by_lua_block – det Ă€r en block som sĂ€ger att vi skickar innehĂ„ll med hjĂ€lp av ett Lua-skript. Vi tar NGINX-variabeln remote_addr och stoppar den i string.format. Det Ă€r samma sak som sprintf, bara pĂ„ Lua, bara korrekt. Och vi skickar det till kunden.

Resultatet ser ut sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Men lÄt oss ÄtervÀnda till verkligheten. Ingen deployar Hello World i produktion. VÄr applikation gör vanligtvis anrop till databasen eller nÄgon annanstans och större delen av tiden vÀntar pÄ svar.

OpenResty: förvandlar NGINX till en komplett applikationsserver

Den sitter bara och vÀntar. Det Àr inte sÄ bra. NÀr 100 000 anvÀndare strömmar in, blir det mycket tufft för oss. SÄ lÄt oss ta fram ett enkelt exempel pÄ en applikation. Vi ska leta efter bilder, till exempel katter. Men vi ska inte bara leta, vi kommer att bredda sökord och om en anvÀndare söker pÄ "kattungar", sÄ ska vi hitta katter, fluffiga, och sÄ vidare. Först mÄste vi fÄ sökdata pÄ backend. Det ser ut sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

TvÄ rader tillÄter dig att hÀmta GET-parametrar, inget krÄngel. DÀrefter fÄr vi informationen frÄn databasen med en table pÄ sökordet och filendelse med en vanlig SQL-frÄga. Det Àr enkelt. Det ser ut sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi kopplar in biblioteket resty.mysql, som vi redan har i paketet. Vi behöver inget installera, allt Àr klart. Vi anger hur vi ansluter och gör en SQL-frÄga:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Det Ă€r lite lĂ€skigt hĂ€r, men allt fungerar. HĂ€r Ă€r 10 – det Ă€r grĂ€nsen. Vi hĂ€mtar 10 poster, vi Ă€r lata och vill inte visa fler. Jag glömde att nĂ€mna grĂ€nsen i SQL.

Sedan hittar vi bilder för alla förfrÄgningar. Vi samlar en hög av förfrÄgningar och fyller en Lua-tabell som kallas reqs, och gör ngx.location.capture_multi.

OpenResty: förvandlar NGINX till en komplett applikationsserver

Alla dessa förfrÄgningar gÄr parallellt, och vi fÄr tillbaka svar. Tiden för arbetet Àr lika med tiden för svaret frÄn den lÄngsammaste. Om alla svarar pÄ 50 millisekunder och vi skickade hundra förfrÄgningar, kommer svaret att komma tillbaka pÄ 50 millisekunder.

Eftersom vi Àr lata och inte vill skriva HTTP-hantering och caching, kommer vi att fÄ NGINX att göra allt Ät oss. Som ni sÄg, dÀr var en förfrÄgan till url/fetch, hÀr Àr den:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi gör en enkel proxy_pass, anger vart vi ska cacha, hur vi ska göra det, och allt fungerar.

Men det Àr inte tillrÀckligt, vi behöver ocksÄ ge data till anvÀndaren. Den enklaste idén Àr att serialisera allt till JSON, lÀtt, pÄ tvÄ rader. Vi ger Content-Type, vi ger JSON.

Men det finns en svÄrighet: anvÀndaren vill inte lÀsa JSON. Vi mÄste locka frontend-utvecklare. Ibland vill vi inte göra det frÄn början. SEO-experter kan sÀga att om vi letar efter bilder Àr det ointressant för dem. Men om vi ger dem nÄgot innehÄll, kommer de att sÀga att vÄra sökmotorer inte indexerar nÄgot.

Vad ska vi göra Ät det? SjÀlvklart kommer vi att ge HTML till anvÀndaren. Att generera det manuellt Àr inte bra, sÄ vi vill anvÀnda mallar. För detta finns det ett bibliotek lua-resty-template.

OpenResty: förvandlar NGINX till en komplett applikationsserver

Ni har kanske sett de tre skrÀmmande bokstÀverna OPM. OpenResty kommer med sin egen pakethanterare, genom vilken man kan installera en massa olika moduler, bland annat lua-resty-template. Det Àr en enkel mallmotor, nÀra Django-mallar. DÀr kan man skriva kod och göra variabelsubstitution.

Resultatet kommer att se ungefÀr ut sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi tog data och renderade mallen igen i tvÄ rader. AnvÀndaren Àr glad, han fick kattbilder. Eftersom vi utvidgade förfrÄgan fick han ocksÄ en sjölejon. Vem vet, kanske han letade just efter det men inte kunde formulera sin förfrÄgan korrekt.

Det Àr fantastiskt, men vi Àr i utvecklingsskedet, och vi vill inte visa det för anvÀndarna Àn. LÄt oss göra autentisering. För att göra det, lÄt oss se hur NGINX hanterar en förfrÄgan i termer av OpenResty:

  • Den första fasen – access, nĂ€r anvĂ€ndaren just har kommit in, och vi har tittat pĂ„ honom utifrĂ„n rubriker, IP-adress och annan information. Vi kan omedelbart stĂ€nga av honom om vi inte gillar det. Detta kan anvĂ€ndas för autentisering, eller om vi fĂ„r vĂ€ldigt mĂ„nga förfrĂ„gningar kan vi enkelt stĂ€nga av dem i detta skede.
  • rewrite. Vi skriver om viss förfrĂ„gningsdata.
  • innehĂ„ll. Vi ger innehĂ„llet till anvĂ€ndaren.
  • rubriksfilter. Vi kan modifiera svarsrubriker. Om vi har anvĂ€nt proxy_pass, kan vi skriva om vissa rubriker innan vi ger dem till anvĂ€ndaren.
  • kroppsförfilter. Vi kan modifiera kroppen.
  • log — loggning. Vi kan skriva loggar i elasticsearch utan ett extra lager.

VÄr autentisering kommer att se ut ungefÀr sÄ hÀr:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi lÀgger till detta i den plats, som vi beskrev tidigare, och sÀtter in följande kod:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi kollar om vi har en cookie-token. Om inte, omdirigerar vi till autentisering. AnvÀndarna Àr kloka och kan lista ut att de behöver sÀtta en cookie-token. DÀrför lÀgger vi Àven in den i Redis:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Koden för att arbeta med Redis Àr vÀldigt enkel och skiljer sig inte frÄn andra sprÄk. All input/output dÀr och hÀr Àr icke-blockerande. Om du skriver synkron kod fungerar det asynkront. UngefÀr som med gevent, fast gjort bra.

OpenResty: förvandlar NGINX till en komplett applikationsserver

LÄt oss göra sjÀlva autentiseringen:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Vi sÀger att vi behöver lÀsa kroppsinnehÄllet för förfrÄgan. Vi fÄr POST-argument, kontrollerar att anvÀndarnamn och lösenord Àr korrekta. Om de Àr felaktiga, omdirigerar vi till autentisering. Men om de Àr korrekta, sparar vi token i Redis:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Glöm inte att sÀtta cookie, det görs ocksÄ pÄ tvÄ rader:

OpenResty: förvandlar NGINX till en komplett applikationsserver

Ett enkelt, hypotetiskt exempel. Vi kommer sjÀlvklart inte att göra en tjÀnst som visar katter för mÀnniskor. Men vem vet. LÄt oss dÀrför titta pÄ vad som kan göras i produktion.

  • Minimalistisk backend. Ibland behöver vi leverera en mycket liten mĂ€ngd data till backend: ibland behöver vi sĂ€tta in ett datum, ibland visa en lista, berĂ€tta hur mĂ„nga anvĂ€ndare som för nĂ€rvarande Ă€r pĂ„ webbplatsen, koppla in en rĂ€knare eller statistik. NĂ„got litet. Minimala bitar kan göras vĂ€ldigt lĂ€tt. Det kommer att bli snabbt, enkelt och bra.
  • Förbehandling av data. Ibland vill vi integrera annonser pĂ„ vĂ„r sida, och vi hĂ€mtar dessa annonser via API-förfrĂ„gningar. Det Ă€r vĂ€ldigt enkelt att göra just hĂ€r. Vi belastar inte vĂ„r backend, som redan arbetar hĂ„rt. Vi kan samla detta hĂ€r. Vi kan skapa lite JS eller, tvĂ€rtom, dela upp det, processa nĂ„got innan vi ger det till anvĂ€ndaren.
  • Facad för mikrotjĂ€nst. Detta Ă€r ocksĂ„ ett mycket bra fall, jag har implementerat det. Tidigare arbetade jag pĂ„ företaget Tenzor, som sysslar med elektronisk rapportering och tillhandahĂ„ller rapportering för ungefĂ€r hĂ€lften av företagen i landet. Vi gjorde en tjĂ€nst dĂ€r med hjĂ€lp av samma mekanism Ă€r mĂ„nga saker gjorda: ruttdelning, autentisering och annat.
    OpenResty kan anvÀndas som lim för dina mikrotjÀnster, vilket ger en enhetlig Ätkomst till allt och ett enhetligt grÀnssnitt. Eftersom mikrotjÀnster kan skrivas sÄ hÀr, sÄ har du Node.js hÀr, PHP dÀr, Python hÀr, nÄgon grej pÄ Erlang, förstÄr vi att vi inte vill skriva samma kod överallt. SÄ OpenResty kan sÀttas pÄ fronten.
  • Statistik och analys. Vanligtvis stĂ„r NGINX vid ingĂ„ngen, och alla förfrĂ„gningar gĂ„r genom honom. Just pĂ„ denna plats Ă€r det mycket bekvĂ€mt att samla. Man kan rĂ€kna nĂ„got direkt och skicka det nĂ„gonstans, till exempel till Elasticsearch, Logstash eller helt enkelt logga det och sedan skicka det nĂ„gonstans.
  • Flerspelarsystem. Till exempel Ă€r det ocksĂ„ mycket bra att göra online-spel. Idag i Kapstaden kommer Alexander Gladysh att berĂ€tta hur man snabbt prototyperar ett flerspelarspel med hjĂ€lp av OpenResty.
  • Filtrering av förfrĂ„gningar (WAF). Nu Ă€r det populĂ€rt att göra alla möjliga web application firewalls, det finns mĂ„nga tjĂ€nster som tillhandahĂ„ller dem. Med hjĂ€lp av OpenResty kan du skapa en web application firewall som enkelt och smidigt filtrerar förfrĂ„gningar enligt dina krav. Om du har Python förstĂ„r du att PHP inte kan injiceras, om du inte spawnar det nĂ„gonstans frĂ„n konsolen. Du vet att du har MySQL och Python. Kanske kan de försöka göra nĂ„gon typ av directory traversal och injicera nĂ„got i databasen. DĂ€rför kan man snabbt och billigt filtrera bort misstĂ€nkt förfrĂ„gningar direkt pĂ„ fronten.
  • Gemenskap. Eftersom OpenResty Ă€r byggt pĂ„ NGINX har det en bonus - det Ă€r NGINX-gemenskapDet Ă€r mycket stort, och en betydande del av de frĂ„gor som du kan ha i början har redan lösts av NGINX-communityt.

    Lua-utvecklareI gÄr pratade jag med killarna som kom pÄ utbildningsdagen HighLoad++ och hörde att endast Tarantool Àr skrivet pÄ Lua. SÄ Àr det inte, det Àr mycket som Àr skrivet i Lua. Exempel: OpenResty, XMPP-servern Prosody, spelmotorn Love2D, Lua scriptas i Warcraft och pÄ andra stÀllen. Det finns mÄnga Lua-utvecklare, och deras community Àr stort och lyhört. Alla mina frÄgor om Lua blev lösta inom nÄgra timmar. NÀr man skriver till mailinglistan fÄr man bokstavligen svar inom nÄgra minuter, de förklarar vad och hur, vad som Àr vad. Det Àr riktigt bra. TyvÀrr Àr det inte alltid sÄ hÀr vÀnligt stÀmning i andra communitys.
    Det finns en GitHub för OpenResty, dĂ€r kan man skapa en issue om nĂ„got gĂ„r sönder. Det finns en mailinglista i Google Groups dĂ€r man kan diskutera allmĂ€nna frĂ„gor, och det finns en lista pĂ„ kinesiska – kanske behĂ€rskar du inte engelska, men kan kinesiska.

Sammanfattning

  • Jag hoppas att jag har kunnat förmedla att OpenResty Ă€r ett vĂ€ldigt bekvĂ€mt ramverk anpassat för webben.
  • Det har en lĂ„g intrĂ€deströskel, eftersom koden liknar det vi skriver, sprĂ„ket Ă€r ganska enkelt och minimalistiskt.
  • Det erbjuder asynkron I/O utan callbacks, sĂ„ vi kommer inte att ha den spagetti-kod som vi ibland kan fĂ„ i NodeJS.
  • Det har en enkel distribution, eftersom vi bara behöver NGINX med rĂ€tt modul och vĂ„r kod, sĂ„ fungerar allt direkt.
  • Ett stort och lyhört community.

Jag gick inte in pÄ detaljer om hur routing görs, det skulle ha blivit en mycket lÄng berÀttelse.

Tack för uppmÀrksamheten!

Spela video

Vladimir Protasov – OpenResty: vi gör NGINX till en fullfjĂ€drad applikationsserver

KĂ€lla: habr.com
Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster