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!


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

Källa: will.com

Lägg en kommentar