OpenResty: gør NGINX til en fuldgyldig applikationsserver

OpenResty: gør NGINX til en fuldgyldig applikationsserverVi offentliggør igen udskriften af ​​konferencens rapport HighLoad ++ 2016, som fandt sted i Skolkovo nær Moskva den 7.-8. november sidste år. Vladimir Protasov forklarer, hvordan man udvider NGINX-funktionaliteten med OpenResty og Lua.

Hej alle sammen, mit navn er Vladimir Protasov, jeg arbejder hos Parallels. Jeg vil fortælle dig lidt om mig selv. Jeg bruger tre fjerdedele af mit liv på at skrive kode. Jeg blev programmør til kernen i bogstavelig forstand: nogle gange ser jeg kode i mine drømme. En fjerdedel af livet er industriel udvikling, at skrive kode, der går direkte i produktion. En kode, som nogle af jer bruger, men som ikke er klar over det.

Så du forstår, hvor slemt det var. Da jeg var lille, kom jeg og fik disse to terabyte databaser. Det er høj belastning for alle her nu. Jeg gik til konferencer og spurgte: "Gunner, fortæl mig, I har big data, er alting fedt? Hvor mange baser har du der? De svarede mig: "Vi har 100 gigabyte!" Jeg sagde: "Fedt, 100 gigabyte!" Og jeg tænkte ved mig selv, hvordan jeg omhyggeligt skulle vedligeholde mit pokeransigt. Du tror, ​​ja, fyrene er seje, og så går du tilbage og piller med disse multi-terabyte-databaser. Og det er at være junior. Kan du forestille dig, hvilket slag dette er?

Jeg kan mere end 20 programmeringssprog. Det var noget, jeg skulle finde ud af, mens jeg arbejdede. De giver dig kode i Erlang, C, C++, Lua, Python, Ruby, noget andet, og du skal skære det hele. Generelt var jeg nødt til det. Det var ikke muligt at beregne det nøjagtige antal, men et sted omkring den 20. gik tallet tabt.

Da alle tilstedeværende ved, hvad Parallels er, og hvad vi laver, vil jeg ikke tale om, hvor seje vi er, og hvad vi laver. Jeg vil bare fortælle dig, at vi har 13 kontorer rundt om i verden, mere end 300 ansatte, udvikling i Moskva, Tallinn og Malta. Hvis du ønsker det, kan du tage det og flytte til Malta, hvis det er koldt om vinteren, og du skal varme ryggen.

Helt konkret skriver vores afdeling i Python 2. Vi er i gang og har ikke tid til at implementere moderigtige teknologier, så vi lider. Vi bruger Django, fordi den har alt, og vi tog det unødvendige og smed det væk. Også MySQL, Redis og NGINX. Vi har også en masse andre fede ting. Vi har MongoDB, vi har kaniner, der render rundt, vi har alt - men det er ikke mit, og jeg gør det ikke.

OpenResty

Jeg fortalte om mig selv. Lad os finde ud af, hvad jeg skal tale om i dag:

  • Hvad er OpenResty, og hvad spises det med?
  • Hvorfor genopfinde endnu et hjul, når vi har Python, NodeJS, PHP, Go og andre fede ting, som alle er glade for?
  • Og et par eksempler fra livet. Jeg måtte skære meget i rapporten, fordi det tog mig 3,5 time, så der vil være få eksempler.

OpenResty er NGINX. Takket være ham har vi en fuldgyldig webserver, der er velskrevet og fungerer hurtigt. Jeg tror, ​​de fleste af os bruger NGINX i produktionen. I ved alle, at han er hurtig og sej. De lavede seje synkron I/O i den, så vi behøver ikke at cykle noget, ligesom de gjorde i Python. Gevent er sejt, fantastisk, men hvis du skriver C-kode, og noget går galt, vil du med Gevent gå amok med at fejlsøge den. Jeg havde oplevelsen: det tog to hele dage at finde ud af, hvad der gik galt der. Hvis nogen ikke havde gravet rundt i flere uger, fundet problemet, skrevet på internettet, og Google ikke havde fundet det, så var vi gået helt amok.

NGINX har allerede caching og statisk indhold udført. Du behøver ikke bekymre dig om, hvordan du gør dette menneskeligt, så du ikke sænker farten et eller andet sted, så du ikke mister deskriptorer et sted. Nginx er meget praktisk at implementere, du behøver ikke tænke på, hvad du skal tage - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx blev installeret, givet til administratorerne, de ved, hvordan man arbejder med det. Nginx behandler anmodninger på en struktureret måde. Jeg vil tale om dette lidt senere. Kort sagt har den en fase, hvor den netop har accepteret anmodningen, hvornår den behandlede den, og hvornår den serverede indholdet til brugeren.

Nginx er cool, men der er et problem: det er ikke fleksibelt nok, selv med alle de fede funktioner, som fyrene har proppet ind i konfigurationen, på trods af hvad der kan konfigureres. Denne magt er ikke nok. Det er derfor, fyrene fra Taobao for lang tid siden, det ser ud til at være otte år siden, byggede Lua ind i det. Hvad giver det?

  • størrelse. Den er lille. LuaJIT giver omkring 100-200 kilobyte hukommelsesomkostninger og minimal ydeevne.
  • hastighed. LuaJIT-tolken er tæt på C i mange situationer, i nogle situationer taber den til Java, i andre overgår den den. I nogen tid blev det anset for at være state of art, den sejeste JIT-kompiler. Nu er der køligere, men de er meget tunge, for eksempel den samme V8. Nogle JS-tolke og Java HotSpot er hurtigere på nogle punkter, men nogle steder taber de stadig.
  • Let at lære. Hvis du f.eks. har en Perl-kodebase, og du ikke booker, finder du ikke Perl-programmører. Fordi de ikke eksisterer, blev de alle taget væk, og det er langt og svært at lære dem. Hvis du vil have programmører til noget andet, skal du måske også omskole dem eller finde dem. I tilfældet med Lua er alt enkelt. Enhver junior kan lære Lua på tre dage. Det tog mig omkring to timer at finde ud af det. To timer senere skrev jeg allerede kode i produktionen. Omkring en uge senere gik han direkte i produktion og gik.

Som et resultat ser det sådan ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Der er meget her. OpenResty har samlet en masse moduler, både luash og motor. Og du har alt klar - installeret og fungerer.

Примеры

Nok af teksterne, lad os gå videre til koden. Her er en lille Hello World:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Hvad er der? Dette er en Engins lokation. Vi bekymrer os ikke, vi skriver ikke vores egen routing, vi tager ikke en færdiglavet en - vi har den allerede i NGINX, vi lever et godt og dovent liv.

content_by_lua_block er en blok, der siger, at vi serverer indhold ved hjælp af et Lua-script. Vi tager Engines-variablen remote_addr og læg den ind string.format. Det er det samme som sprintf, kun i Lua, kun korrekt. Og vi giver det til kunden.

Som et resultat vil det se sådan ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Men lad os vende tilbage til den virkelige verden. Ingen implementerer Hello World til produktion. Vores ansøgning går normalt til databasen eller et andet sted, og det meste af tiden venter på et svar.

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Han sidder bare og venter. Det er ikke særlig godt. Når der kommer 100.000 brugere, er det meget svært for os. Så lad os bruge en simpel applikation som eksempel. Vi vil lede efter billeder af f.eks. katte. Men vi vil ikke bare søge, vi udvider søgeordene, og hvis brugeren søgte efter "killinger", vil vi finde katte, lodne katte og så videre. Først skal vi få anmodningsdataene på backend. Det ser sådan ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

To linjer giver dig mulighed for at opfange GET-parametre uden komplikationer. Lad os dernæst sige, at fra en database med et tegn for et nøgleord og en udvidelse, får vi disse oplysninger ved hjælp af en almindelig SQL-forespørgsel. Det er simpelt. Det ser sådan ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Tilslutning af biblioteket resty.mysql, som vi allerede har i sættet. Vi behøver ikke installere noget, alt er klar. Vi angiver, hvordan du forbinder og laver en SQL-forespørgsel:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Det er lidt skræmmende her, men alt fungerer. Her er 10 grænsen. Vi trækker 10 bidrag ud, vi er dovne, vi vil ikke vise mere. Jeg glemte grænsen i SQL.

Dernæst finder vi billeder til alle forespørgsler. Vi samler en masse forespørgsler og udfylder en Lua-tabel kaldet reqs, og det gør vi ngx.location.capture_multi.

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Alle disse forespørgsler sendes parallelt, og svar returneres til os. Driftstiden er lig med reaktionstiden for den langsomste. Hvis vi alle skyder på 50 millisekunder, og vi har sendt hundrede anmodninger, så vil vi modtage et svar om 50 millisekunder.

Da vi er dovne og ikke ønsker at skrive HTTP og cachehåndtering, får vi NGINX til at gøre alt for os. Som du så, var der en anmodning om url/fetch, her er han:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Vi gør det enkelt proxy_pass, vi angiver, hvor der skal cachelagres, hvordan man gør det, og alt fungerer for os.

Men det er ikke nok, vi skal stadig give dataene til brugeren. Den enkleste idé er at serialisere alt i JSON, nemt, i to linjer. Vi giver Content-Type, vi giver JSON.

Men der er en vanskelighed: brugeren ønsker ikke at læse JSON. Vi skal tiltrække frontend-udviklere. Nogle gange ønsker vi ikke at gøre dette i starten. Og SEO-specialister vil sige, at hvis vi leder efter billeder, så er det lige meget for dem. Og hvis vi giver dem noget indhold, vil de sige, at vores søgemaskiner ikke indekserer noget.

Hvad skal man gøre ved det? Vi vil selvfølgelig give brugeren HTML. At generere i hånden er ikke comme il faut, så vi vil bruge skabeloner. Der er et bibliotek til dette lua-resty-template.

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Du har sikkert set de tre skræmmende bogstaver OPM. OpenResty kommer med sin egen pakkehåndtering, hvorigennem du kan installere en masse forskellige moduler, især, lua-resty-template. Dette er en simpel skabelonmotor, der ligner Django-skabeloner. Der kan du skrive kode og udføre variabel substitution.

Som et resultat vil alt se sådan ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Vi tog dataene og gengav skabelonen igen på to linjer. Brugeren er glad, han modtog katte. Da vi udvidede anmodningen, modtog han også en pelssæl til killinger. Man ved aldrig, måske ledte han efter netop dette, men kunne ikke formulere sin anmodning korrekt.

Alt er fedt, men vi er i udvikling og ønsker ikke at vise det til brugerne endnu. Lad os udføre autorisation. For at gøre dette, lad os se på, hvordan NGINX håndterer anmodningen i OpenResty-vilkår:

  • Første fase - adgang, da brugeren lige er ankommet, og vi så på ham efter overskrifter, efter IP-adresse og efter andre data. Vi kan straks afskære det, hvis vi ikke kan lide det. Dette kan bruges til godkendelse, eller hvis vi modtager mange anmodninger, kan vi nemt afbryde dem i denne fase.
  • omskrivning. Vi omskriver nogle anmodningsdata.
  • indhold. Vi leverer indholdet til brugeren.
  • overskrifter filter. Vi udskifter svaroverskrifterne. Hvis vi brugte proxy_pass, kan vi omskrive nogle overskrifter, før vi giver det til brugeren.
  • kropsfilter. Vi kan ændre kroppen.
  • log - logning. Du kan skrive logs i elasticsearch uden et ekstra lag.

Vores autorisation vil se nogenlunde således ud:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Vi tilføjer dette til den location, som vi beskrev før, og læg følgende kode der:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Vi ser efter, om vi har et cookie-token. Hvis ikke, beder vi om tilladelse. Brugere er snedige og kan gætte, at de skal indstille et cookie-token. Derfor vil vi også lægge det i Redis:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Koden til at arbejde med Redis er meget enkel og adskiller sig ikke fra andre sprog. Samtidig er al input/output her og der ikke blokerende. Hvis du skriver synkron kode, fungerer det asynkront. Næsten som gavt, men gjort godt.

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Lad os selv udføre autorisationen:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Vi siger, at vi skal læse selve anmodningen. Vi modtager POST-argumenter og kontrollerer, at login og adgangskode er korrekte. Hvis de er forkerte, så udfordrer vi dig om autorisation. Og hvis det er korrekt, så skriv tokenet i Redis:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Glem ikke at sætte cookien, dette gøres også på to linjer:

OpenResty: gør NGINX til en fuldgyldig applikationsserver

Eksemplet er enkelt og spekulativt. Vi vil selvfølgelig ikke lave en service, der viser folk katte. Men hvem kender os. Så lad os gennemgå, hvad der kan gøres i produktionen.

  • Minimalistisk backend. Nogle gange har vi brug for at udlæse en lille smule data til backend: et eller andet sted skal vi indsætte en dato, et eller andet sted skal vi vise en liste, sige hvor mange brugere der er på siden nu, vedhæfte en tæller eller statistik. Noget så småt. Nogle minimale stykker kan laves meget nemt. Dette vil gøre det hurtigt, nemt og fantastisk.
  • Dataforbehandling. Nogle gange ønsker vi at integrere annoncering på vores side, og vi modtager denne annoncering ved hjælp af API-anmodninger. Det er meget nemt at gøre her. Vi loader ikke vores backend, som allerede sidder og arbejder hårdt. Du kan hente den og afhente den her. Vi kan flette noget JS sammen eller omvendt afkoble det og forbehandle noget, før vi giver det til brugeren.
  • Facade til mikroservice. Dette er også en meget god sag, jeg implementerede den. Før det arbejdede jeg hos Tenzor, en virksomhed, der beskæftiger sig med elektronisk rapportering og leverer rapportering til cirka halvdelen af ​​de juridiske enheder i landet. Vi oprettede en tjeneste, mange ting blev gjort der ved hjælp af den samme mekanisme: routing, autorisation og mere.
    OpenResty kan bruges som limen til dine mikrotjenester, hvilket giver en enkelt adgang til alt og en enkelt grænseflade. Da mikrotjenester kan skrives på en sådan måde, at du har Node.js her, PHP her, Python her, noget Erlang her, forstår vi, at vi ikke ønsker at omskrive den samme kode overalt. Derfor kan OpenResty sættes i fronten.

  • Statistik og analyser. Normalt er NGINX ved indgangen, og alle anmodninger går igennem den. Det er på dette sted, at det er meget praktisk at samle. Du kan med det samme beregne noget og uploade det et sted, for eksempel Elasticsearch, Logstash, eller blot skrive det til loggen og derefter sende det et sted hen.
  • Flerbruger systemer. For eksempel er online spil også meget gode at lave. I dag i Cape Town vil Alexander Gladysh fortælle om, hvordan man hurtigt prototyper et multiplayer-spil ved hjælp af OpenResty.
  • Anmod om filtrering (WAF). I dag er det moderne at lave alle mulige webapplikationsfirewalls; der er mange tjenester, der leverer dem. Ved hjælp af OpenResty kan du lave dig selv en webapplikations-firewall, der enkelt og nemt vil filtrere anmodninger efter dine krav. Hvis du har Python, så forstår du, at PHP bestemt ikke vil blive injiceret i dig, medmindre du selvfølgelig spawner det overalt fra konsollen. Du ved, at du har MySQL og Python. Sandsynligvis kan de prøve at lave en form for mappegennemgang og injicere noget i databasen. Derfor kan du frafiltrere mærkelige forespørgsler hurtigt og billigt lige ved fronten.
  • Fællesskab. Da OpenResty er bygget på NGINX, har den en bonus - denne NGINX-fællesskab. Det er meget stort, og en anstændig del af de spørgsmål, du vil have i starten, er allerede blevet løst af NGINX-fællesskabet.

    Lua udviklere. I går talte jeg med de fyre, der kom til HighLoad++ træningsdagen og hørte, at kun Tarantool var skrevet i Lua. Dette er ikke sandt, mange ting er skrevet i Lua. Eksempler: OpenResty, Prosody XMPP-server, Love2D-spilmotor, Lua scriptet i Warcraft og andre steder. Der er mange Lua-udviklere, de har et stort og lydhørt fællesskab. Alle mine Lua-spørgsmål blev løst inden for et par timer. Når du skriver til mailinglisten, er der bogstaveligt talt inden for et par minutter allerede en masse svar, der beskriver hvad og hvordan, hvad er hvad. Det er godt. Desværre er sådan et åndeligt fællesskab ikke overalt.
    Der er GitHub til OpenResty, hvor du kan åbne et problem, hvis noget går i stykker. Der er en mailingliste på Google Groups, hvor du kan diskutere generelle spørgsmål, der er en mailingliste på kinesisk - du ved aldrig, måske taler du ikke engelsk, men du kan kinesisk.

Resultaterne af

  • Jeg håber, jeg var i stand til at formidle, at OpenResty er en meget praktisk ramme, der er skræddersyet til nettet.
  • Den har en lav adgangsbarriere, da koden ligner det vi skriver i, sproget er ret simpelt og minimalistisk.
  • Det giver asynkron I/O uden tilbagekald, vi vil ikke have nogen nudler, som vi nogle gange kan skrive i NodeJS.
  • Det er nemt at installere, da vi kun har brug for NGINX med det nødvendige modul og vores kode, og alt fungerer med det samme.
  • Stort og lydhørt fællesskab.

Jeg fortalte ikke i detaljer, hvordan routing foregår, det viste sig at være en meget lang historie.

Tak for din opmærksomhed!


Vladimir Protasov - OpenResty: gør NGINX til en fuldgyldig applikationsserver

Kilde: www.habr.com

Tilføj en kommentar