OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

OpenResty: gör NGINX till en fullfjÀdrad applikationsserverVi Äterpublicerar utskriften av rapporten frÄn konferensen högbelastningstillstÄnd ++ 2016, som hölls i Skolkovo nÀra Moskva den 7-8 november förra Äret. Vladimir Protasov berÀttar hur man utökar NGINX-funktionaliteten med OpenResty och Lua.

Hej alla, jag heter Vladimir Protasov, jag jobbar för Parallels. Jag ska berÀtta lite om mig sjÀlv. Jag Àgnar tre fjÀrdedelar av mitt liv Ät att skriva kod. Jag blev en programmerare till kÀrnan i bokstavlig mening: jag ser ibland kod i mina drömmar. En fjÀrdedel av livet Àr industriell utveckling, att skriva kod som gÄr direkt in i produktionen. Kod som nÄgra av er anvÀnder men inte kÀnner till det.

För att berĂ€tta hur illa det var. NĂ€r jag var liten kom jag in och de gav mig dessa tvĂ„ terabyte-databaser. Det Ă€r nu hĂ€r för alla highload. Jag gick pĂ„ konferenser och frĂ„gade: ”Gubbar, sĂ€g mig, har ni big data, Ă€r allt coolt? Hur mĂ„nga baser har du dĂ€r? De svarade mig: "Vi har 100 gigabyte!" Jag sa: "Cool, 100 gigabyte!" Och jag tĂ€nkte för mig sjĂ€lv hur man snyggt skulle kunna rĂ€dda pokeransiktet. Du tror, ​​ja, killarna Ă€r coola, och sedan kommer du tillbaka och pysslar med dessa multi-terabyte-databaser. Och det hĂ€r Ă€r att vara junior. Kan du förestĂ€lla dig vilken hit det Ă€r?

Jag kan mer Àn 20 programmeringssprÄk. Detta var vad jag var tvungen att ta reda pÄ under arbetets gÄng. De ger dig kod i Erlang, i C, i C++, i Lua, i Python, i Ruby, i nÄgot annat, och du mÄste klippa allt. I allmÀnhet var jag tvungen. Det var inte möjligt att berÀkna det exakta antalet, men nÄgonstans runt 20 gick siffran borta.

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

NĂ€rmare bestĂ€mt skriver vĂ„r avdelning i Python 2. Vi Ă€r i affĂ€rer och vi har inte tid att introducera fashionabla teknologier, sĂ„ vi lider. Vi har Django, för den har allt, och vi tog överskottet och slĂ€ngde det. Även MySQL, Redis och NGINX. Vi har ocksĂ„ en massa andra coola grejer. Vi har MongoDB, vi har kaniner som springer runt, vi har bara ingenting - men det Ă€r inte mitt, och jag gör det inte.

OpenResty

Jag berÀttade om mig sjÀlv. LÄt oss se vad jag ska prata om idag:

  • Vad Ă€r OpenResty och vad Ă€ts det med?
  • Varför Ă„teruppfinna hjulet nĂ€r vi har Python, NodeJS, PHP, Go och andra coola grejer som alla Ă€r nöjda med?
  • Och nĂ„gra verkliga exempel. Jag var tvungen att skĂ€ra ner rapporten mycket, eftersom jag fick den i 3,5 timmar, sĂ„ det blir fĂ„ exempel.

OpenResty Àr NGINX. Tack vare honom har vi en fullfjÀdrad webbserver, som Àr vÀlskriven, den fungerar snabbt. Jag tror att de flesta av oss anvÀnder NGINX i produktionen. Ni vet alla att han Àr snabb och cool. De gjorde coola synkrona I/O i den, sÄ vi behöver inte cykla nÄgot pÄ samma sÀtt som gevent cyklades i Python. Gevent Àr coolt, coolt, men om du skriver C-kod och nÄgot gÄr fel med gevent kommer du att bli galen av att felsöka den. Jag hade erfarenhet: det tog tvÄ hela dagar att ta reda pÄ vad som gick fel dÀr. Om nÄgon inte hade grÀvt pÄ nÄgra veckor innan, hittat problemet, skrivit det pÄ internet och Google inte hittat det, dÄ hade vi blivit helt galna.

NGINX gör redan cachning och statiskt innehÄll. Du behöver inte oroa dig för hur du gör det mÀnskligt, sÄ att du inte saktar ner nÄgonstans, sÄ att du inte tappar deskriptorer nÄgonstans. Nginx Àr vÀldigt bekvÀmt att distribuera, du behöver inte tÀnka pÄ vad du ska ta - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx installerades, givet till administratörerna, de vet hur man arbetar med det. Nginx behandlar förfrÄgningar pÄ ett strukturerat sÀtt. Jag ska prata om detta lite senare. Kort sagt, han har en fas nÀr han precis accepterade förfrÄgan, nÀr han bearbetade och nÀr han gav innehÄllet till anvÀndaren.

Nginx Àr coolt, men det finns ett problem: det Àr inte tillrÀckligt flexibelt Àven med alla de dÀr coola funktionerna som killarna tryckte in i konfigurationen, trots att det gÄr att anpassa. Denna kraft rÀcker inte. DÀrför byggde killarna frÄn Taobao en gÄng, jag tror för ungefÀr Ätta Är sedan, in Lua i den. Vad ger han?

  • Storlek. Den Ă€r liten. LuaJIT ger nĂ„gonstans runt 100-200 kilobyte minnesoverhead och minimal prestandaoverhead.
  • ĐĄĐșĐŸŃ€ĐŸŃŃ‚ŃŒ. LuaJIT-tolken Ă€r nĂ€ra C i mĂ„nga situationer, i vissa situationer förlorar den mot Java, i vissa kör den om den. Ett tag ansĂ„gs det vara toppmodernt, den coolaste JIT-kompilatorn. Nu finns det svalare, men de Ă€r vĂ€ldigt tunga, till exempel samma V8. Vissa JS-tolkar och Java HotSpot Ă€r snabbare pĂ„ vissa punkter, men förlorar fortfarande pĂ„ vissa punkter.
  • LĂ€tt att lĂ€ra. Om du har, sĂ€g, en Perl-kodbas och du inte bokar, kommer du inte att hitta Perl-programmerare. Eftersom de inte Ă€r dĂ€r togs de alla bort, och det Ă€r lĂ„ngt och svĂ„rt att lĂ€ra dem. Vill man ha programmerare till nĂ„got annat kan de ocksĂ„ behöva omskolas eller hittas. NĂ€r det gĂ€ller Lua Ă€r allt enkelt. Lua kan lĂ€ras av alla juniorer pĂ„ tre dagar. Det tog mig ungefĂ€r tvĂ„ timmar att komma pĂ„ det. TvĂ„ timmar senare skrev jag redan kod i produktionen. UngefĂ€r en vecka senare gick han direkt till produktionen och gick.

Som ett resultat ser det ut sÄ hÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Det finns mycket hÀr. OpenResty har satt ihop ett gÀng moduler, bÄde luash och motorer. Och du har allt klart - utplacerat och fungerar.

ĐŸŃ€ĐžĐŒĐ”Ń€Ń‹

Nog med sÄngtexterna, lÄt oss gÄ vidare till koden. HÀr Àr en liten Hello World:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vad finns det? detta Àr motorns plats. Vi oroar oss inte, vi skriver inte vÄr egen routing, vi tar inte nÄgon fÀrdig - vi har den redan i NGINX, vi lever bra och lat.

content_by_lua_block Àr ett block som sÀger att vi serverar innehÄll med ett Lua-skript. Vi tar en motorvariabel remote_addr och skjut in den string.format. Detta Àr samma som sprintf, bara i Lua, bara korrekt. Och vi ger det till kunden.

Som ett resultat kommer det att se ut sÄ hÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Men tillbaka till den verkliga vÀrlden. I produktionen anvÀnder ingen Hello World. VÄr applikation gÄr vanligtvis till databasen eller nÄgon annanstans och för det mesta vÀntar den pÄ svar.

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Sitter bara och vÀntar. Det Àr inte sÀrskilt bra. NÀr 100.000 XNUMX anvÀndare kommer Àr det vÀldigt svÄrt för oss. LÄt oss dÀrför anvÀnda en enkel applikation som exempel. Vi kommer att leta efter bilder, till exempel katter. Bara vi kommer inte bara att söka, vi kommer att utöka nyckelorden och, om anvÀndaren sökte efter "kattungar", kommer vi att hitta katter, fluffies och sÄ vidare. Först mÄste vi fÄ förfrÄgningsdata pÄ backend. Det ser ut sÄ hÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

TvÄ rader lÄter dig plocka upp GET-parametrar, inga komplikationer. Sedan fÄr vi till exempel denna information frÄn en databas med en tabell per nyckelord och tillÀgg med hjÀlp av en vanlig SQL-frÄga. Allt Àr enkelt. Det ser ut sÄ hÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi kopplar ihop biblioteket resty.mysql, som vi redan har i satsen. Vi behöver inte installera nÄgot, allt Àr klart. Ange hur du ansluter och gör en SQL-frÄga:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Det Àr lite lÀskigt, men det fungerar. HÀr Àr 10 grÀnsen. Vi drar ut 10 skivor, vi Àr lata, vi vill inte visa fler. I SQL glömde jag grÀnsen.

Sedan hittar vi bilder för alla frÄgor. Vi samlar ett gÀng förfrÄgningar och fyller i en Lua-tabell som heter reqs, och gör ngx.location.capture_multi.

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Alla dessa förfrĂ„gningar gĂ„r parallellt, och svaren skickas tillbaka till oss. Körtiden Ă€r lika med svarstiden för den lĂ„ngsammaste. Om vi ​​alla skjuter tillbaka pĂ„ 50 millisekunder, och vi skickade hundra förfrĂ„gningar, kommer vi att fĂ„ ett svar inom 50 millisekunder.

Eftersom vi Àr lata och inte vill skriva HTTP-hantering och cachelagring kommer vi att fÄ NGINX att göra allt Ät oss. Som ni sÄg fanns det en begÀran om url/fetch, hÀr Àr han:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi gör enkelt proxy_pass, ange var du ska cache, hur du gör det och allt fungerar för oss.

Men detta rÀcker inte, vi mÄste fortfarande ge data till anvÀndaren. Den enklaste idén Àr att serialisera allt till JSON, enkelt, i 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 attrahera frontend-utvecklare. Ibland kÀnner vi inte för att göra det först. Ja, och SEO-specialister kommer att sÀga att om vi letar efter bilder, sÄ bryr de sig inte. Och om vi ger dem lite innehÄll kommer de att sÀga att vÄra sökmotorer inte indexerar nÄgonting.

Vad ska man göra med det? Naturligtvis kommer vi att ge anvÀndaren HTML. Att generera med handtag Àr inte comme il faut, sÄ vi vill anvÀnda mallar. Det finns ett bibliotek för detta lua-resty-template.

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Du mÄste ha sett de tre fruktade bokstÀverna OPM. OpenResty kommer med sin egen pakethanterare, genom vilken du kan installera en massa olika moduler, i synnerhet, lua-resty-template. Det Àr en enkel mallmotor som liknar Django-mallar. DÀr kan du skriva kod och göra variabelsubstitution.

Som ett resultat kommer allt att se ut ungefÀr sÄ hÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi tog data och renderade mallen igen pÄ tvÄ rader. AnvÀndaren Àr nöjd, fick katter. Eftersom vi utökade förfrÄgan fick han Àven en pÀlssÀl till kattungar. Man vet aldrig, han kanske letade efter det, men han kunde inte formulera sin begÀran korrekt.

Allt Àr coolt, men vi Àr under utveckling och vi vill inte visa anvÀndarna Ànnu. LÄt oss göra en auktorisation. För att göra detta, lÄt oss se hur NGINX hanterar begÀran nÀr det gÀller OpenResty:

  • Första fasen - tillgĂ„ng, nĂ€r anvĂ€ndaren precis kom, och vi tittade pĂ„ honom efter rubriker, efter IP-adress, efter annan data. Du kan genast hugga av den om vi inte gillar den. Detta kan anvĂ€ndas för auktorisering, eller om vi fĂ„r mĂ„nga förfrĂ„gningar kan vi enkelt hacka dem i denna fas.
  • omskrivning. Skriver om en del förfrĂ„gningsdata.
  • innehĂ„ll. Vi ger innehĂ„ll till anvĂ€ndaren.
  • rubrikfilter. Ändra svarsrubriker. Om vi ​​anvĂ€nde proxy_pass, kan vi skriva om nĂ„gra rubriker innan vi ger det till anvĂ€ndaren.
  • kroppsfilter. Vi kan förĂ€ndra kroppen.
  • log - loggning. Det Ă€r möjligt att skriva loggar i elasticsearch utan extra lager.

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

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi lÀgger till det location, som vi beskrev tidigare, och satte följande kod dÀr:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi tittar för att se om vi har en cookie-token. Om inte, sÄ kastar vi pÄ auktorisation. AnvÀndare Àr listiga och kan gissa att en cookie-token mÄste stÀllas in. DÀrför kommer vi ocksÄ att lÀgga det i Redis:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Koden för att arbeta med Redis Àr vÀldigt enkel och skiljer sig inte frÄn andra sprÄk. Samtidigt, all input / output, vad som finns dÀr, vad som finns hÀr, det blockerar inte. Om du skriver synkron kod sÄ fungerar det asynkront. Som med gevent, bara gjort bra.

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

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

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Vi sÀger att vi mÄste lÀsa förfrÄgningsorganet. Vi fÄr POST-argument, kontrollera att inloggning och lösenord Àr korrekta. Om det Àr felaktigt, sÄ lÀgger vi pÄ auktorisation. Och om de Àr korrekta, sÄ skriver vi token till Redis:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Glöm inte att stÀlla in kakan, detta görs ocksÄ pÄ tvÄ rader:

OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

Exemplet Àr enkelt, spekulativt. SjÀlvklart kommer vi inte att göra en tjÀnst som visar katter för mÀnniskor. Men vem kÀnner oss. SÄ lÄt oss gÄ igenom vad som kan göras i produktionen.

  • Minimalistisk backend. Ibland behöver vi ge ut en hel del data till backend: nĂ„gonstans mĂ„ste vi ersĂ€tta datumet, nĂ„gonstans mĂ„ste vi visa nĂ„gon slags lista, sĂ€ga hur mĂ„nga anvĂ€ndare som Ă€r pĂ„ sajten nu, skruva pĂ„ en rĂ€knare eller statistik. NĂ„got sĂ„ litet. Vissa minimala bitar kan göras mycket enkelt. Detta kommer att bli snabbt, enkelt och bra.
  • Dataförbehandling. Ibland vill vi bĂ€dda in annonser pĂ„ vĂ„r sida, och vi tar dessa annonser med API-förfrĂ„gningar. Detta Ă€r vĂ€ldigt enkelt att göra hĂ€r. Vi laddar inte vĂ„r backend, som redan jobbar hĂ„rt. Du kan hĂ€mta och hĂ€mta hĂ€r. Vi kan forma en del JS eller tvĂ€rtom lossa, förbehandla nĂ„got innan vi ger det till anvĂ€ndaren.
  • Fasad för mikroservice. Detta Ă€r ocksĂ„ ett mycket bra fall, jag genomförde det. Innan dess arbetade jag för Tenzor, ett elektroniskt rapporteringsföretag som tillhandahĂ„ller rapportering för ungefĂ€r hĂ€lften av de juridiska personerna i landet. Vi har skapat en tjĂ€nst, mĂ„nga saker görs dĂ€r med samma mekanism: routing, auktorisering och mer.
    OpenResty kan anvÀndas som lim för dina mikrotjÀnster för att ge en enda Ätkomst till allt och ett enda grÀnssnitt. Eftersom mikrotjÀnster kan skrivas pÄ ett sÄdant sÀtt att du har Node.js hÀr, du har PHP hÀr, du har Python hÀr, det finns nÄgon Erlang-grej hÀr, vi förstÄr att vi inte vill skriva om samma kod överallt. DÀrför kan OpenResty kopplas in i fronten.
  • Statistik och analyser. Vanligtvis Ă€r NGINX vid ingĂ„ngen, och alla förfrĂ„gningar gĂ„r igenom den. Det Ă€r pĂ„ denna plats som det Ă€r mycket bekvĂ€mt att samla. Du kan omedelbart berĂ€kna nĂ„got och slĂ€nga det nĂ„gonstans, till exempel samma Elasticsearch, Logstash, eller bara skriva det till loggen och sedan skicka det nĂ„gonstans.
  • FleranvĂ€ndarsystem. Till exempel Ă€r onlinespel ocksĂ„ vĂ€ldigt bra att göra. Idag i Kapstaden kommer Alexander Gladysh att berĂ€tta för dig hur du snabbt prototypar ett spel för flera spelare med OpenResty.
  • BegĂ€r filtrering (WAF). Nu Ă€r det pĂ„ modet att göra alla typer av webbapplikationsbrandvĂ€ggar, det finns mĂ„nga tjĂ€nster som tillhandahĂ„ller dem. Med hjĂ€lp av OpenResty kan du göra dig sjĂ€lv en webbapplikationsbrandvĂ€gg, som enkelt och enkelt filtrerar förfrĂ„gningar efter dina krav. Om du har Python förstĂ„r du att PHP definitivt inte kommer att injiceras till dig, sĂ„vida du naturligtvis inte skapar det nĂ„gonstans frĂ„n konsolen. Du vet att du har MySQL och Python. Förmodligen kan de hĂ€r försöka göra nĂ„gon form av katalogtraversering och injicera nĂ„got i databasen. DĂ€rför kan du filtrera bort dumma förfrĂ„gningar snabbt och billigt direkt lĂ€ngst fram.
  • Gemenskap. Eftersom OpenResty Ă€r baserat pĂ„ NGINX har det en bonus – det hĂ€r Ă€r NGINX community. Den Ă€r vĂ€ldigt stor och mĂ„nga av de frĂ„gor du kommer att ha till en början har redan besvarats av NGINX-communityt.

    Lua utvecklare. IgÄr pratade jag med killarna som kom till HighLoad ++ trÀningsdagen och hörde att bara Tarantool Àr skrivet i Lua. Det Àr inte sÄ, mÄnga saker skrivs i Lua. Exempel: OpenResty, Prosody XMPP-server, Love2D-spelmotor, Lua Àr skriptad i Warcraft och pÄ andra stÀllen. Det finns mÄnga Lua-utvecklare, de har en stor och lyhörd community. Alla mina Lua-frÄgor besvarades inom nÄgra timmar. NÀr du skriver till e-postlistan finns det bokstavligen pÄ nÄgra minuter redan ett gÀng svar, de beskriver vad och hur, vad Àr vad. Det Àr toppen. TyvÀrr finns inte en sÄdan uppriktig gemenskap överallt.
    OpenResty har GitHub, dÀr du kan öppna ett problem om nÄgot gÄr sönder. Det finns en e-postlista pÄ Google Groups dÀr du kan diskutera allmÀnna frÄgor, det finns en e-postlista pÄ kinesiska - du vet aldrig, du kanske inte pratar engelska, men du har kunskaper i kinesiska.

Resultat av

  • Jag hoppas att jag kunde förmedla att OpenResty Ă€r ett mycket bekvĂ€mt webbramverk.
  • Den har en lĂ„g tröskel för intrĂ€de, eftersom koden liknar det vi skriver, Ă€r sprĂ„ket ganska enkelt och minimalistiskt.
  • Det ger asynkron I/O utan callbacks, vi kommer inte ha nudlar som vi ibland kan skriva i NodeJS.
  • Den har en enkel implementering, eftersom vi bara behöver NGINX med rĂ€tt modul och vĂ„r kod, och allt fungerar direkt.
  • Stor och lyhörd gemenskap.

Jag berÀttade inte i detalj hur routing gÄr till, det visade sig vara en vÀldigt lÄng historia.

Tack för din uppmÀrksamhet!

Spela upp video

Vladimir Protasov - OpenResty: gör NGINX till en fullfjÀdrad applikationsserver

KĂ€lla: will.com

LĂ€gg en kommentar