OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnikPonovno objavljamo prepis poročila s konference HighLoad ++ 2016, ki je potekal v Skolkovu pri Moskvi 7. in 8. novembra lani. Vladimir Protasov pove, kako razširiti funkcionalnost NGINX z OpenResty in Lua.

Pozdravljeni vsi, moje ime je Vladimir Protasov, delam za Parallels. Povedal vam bom nekaj o sebi. Tri četrtine svojega življenja porabim za pisanje kode. Postal sem programer do jedra v dobesednem smislu: kodo včasih vidim v sanjah. Četrtina življenja je industrijski razvoj, pisanje kode, ki gre neposredno v proizvodnjo. Koda, ki jo nekateri uporabljate, a je ne poznate.

Da veš, kako hudo je bilo. Ko sem bil mlajši, sem prišel in dali so mi ti dve terabajtni bazi podatkov. Zdaj je tukaj za vsakogar. Šel sem na konference in vprašal: »Fantje, povejte mi, ali imate velike podatke, je vse v redu? Koliko baz imate tam? Odgovorili so mi: "Imamo 100 gigabajtov!" Rekel sem: "Kul, 100 gigabajtov!" In pomislil sem, kako lepo rešiti poker obraz. Misliš, da, fantje so kul, potem pa se vrneš in se poigravaš s temi večterabajtnimi bazami podatkov. In to je biti mladinec. Si predstavljate, kakšna uspešnica je to?

Poznam več kot 20 programskih jezikov. To sem moral ugotoviti med delom. Dajo vam kodo v Erlangu, v C, v C++, v Lui, v Pythonu, v Rubyju, v nečem drugem, in vse to morate zmanjšati. Na splošno sem moral. Natančnega števila ni bilo mogoče izračunati, nekje okoli 20 pa se je število izgubilo.

Ker tukaj vsi vedo, kaj je Parallels in kaj počnemo, ne bom govoril o tem, kako kul smo in kaj počnemo. Povedal vam bom le, da imamo 13 pisarn po vsem svetu, več kot 300 zaposlenih, razvoj v Moskvi, Talinu in na Malti. Če želite, lahko vzamete in se preselite na Malto, če je pozimi hladno in morate ogreti hrbet.

Natančneje, naš oddelek piše v Python 2. Smo v poslu in nimamo časa za uvajanje modnih tehnologij, zato trpimo. Imamo Django, ker ima vse, odvečno pa smo vzeli in zavrgli. Tudi MySQL, Redis in NGINX. Imamo tudi veliko drugih kul stvari. Imamo MongoDB, imamo zajce, ki tekajo naokoli, preprosto nimamo ničesar - vendar ni moj in tega ne počnem.

OpenResty

Povedal sem o sebi. Poglejmo, o čem bom danes govoril:

  • Kaj je OpenResty in s čim ga jemo?
  • Zakaj bi znova izumljali kolesje, ko pa imamo Python, NodeJS, PHP, Go in druge kul stvari, s katerimi so vsi zadovoljni?
  • In nekaj primerov iz resničnega življenja. Poročilo sem moral precej skrajšati, saj sem ga dobil za 3,5 ure, tako da bo primerov malo.

OpenResty je NGINX. Zahvaljujoč njemu imamo popoln spletni strežnik, ki je dobro napisan, deluje hitro. Mislim, da večina od nas uporablja NGINX v proizvodnji. Vsi veste, da je hiter in kul. V njem so naredili kul sinhroni V/I, tako da nam ni treba ničesar ciklirati na enak način, kot je bil gevent cikliran v Pythonu. Gevent je kul, kul, toda če pišete C-kodo in gre kaj narobe z geventom, se vam bo zmešalo, ko boste odpravljali napake. Imel sem izkušnje: trajalo je cela dva dneva, da sem ugotovil, kaj je šlo tam narobe. Če ne bi nekdo prej nekaj tednov kopal, našel težave, napisal na internet, Google pa je ne bi našel, potem bi čisto znoreli.

NGINX že izvaja predpomnjenje in statično vsebino. Ni vam treba skrbeti, kako to narediti človeško, da ne boste nekje upočasnili, da ne boste nekje izgubili deskriptorjev. Nginx je zelo priročen za uvajanje, ni vam treba razmišljati, kaj bi vzeli - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx je bil nameščen, dan adminom, oni znajo delati z njim. Nginx obdeluje zahteve na strukturiran način. O tem bom govoril malo kasneje. Skratka, ima fazo, ko je samo sprejel zahtevo, kdaj je obdelal in kdaj je dal vsebino uporabniku.

Nginx je kul, vendar obstaja en problem: ni dovolj prilagodljiv niti z vsemi tistimi kul funkcijami, ki so jih fantje potisnili v konfiguracijo, kljub dejstvu, da ga je mogoče prilagoditi. Ta moč ni dovolj. Zato so fantje iz Taobaa nekoč, mislim, da pred osmimi leti, vanj vgradili Luo. Kaj daje?

  • Velikost. Je majhno. LuaJIT daje nekje okoli 100-200 kilobajtov pomnilnika in minimalne stroške delovanja.
  • Hitro. Tolmač LuaJIT je v mnogih situacijah blizu C-ja, v nekaterih situacijah izgubi Javo, v nekaterih jo prehiti. Nekaj ​​časa je veljal za najsodobnejši, najbolj kul prevajalnik JIT. Zdaj obstajajo hladnejši, vendar so zelo težki, na primer isti V8. Nekateri tolmači JS in Java HotSpot so na nekaterih točkah hitrejši, vendar na nekaterih točkah še vedno izgubijo.
  • Enostaven za učenje. Če imate, recimo, kodno zbirko Perl in niste Booking, ne boste našli Perl programerjev. Ker jih ni, so jih vse odpeljali, učiti jih je dolgo in težko. Če želite programerje za kaj drugega, jih bo morda treba tudi prekvalificirati ali poiskati. V primeru Lua je vse preprosto. Lua se lahko vsak junior nauči v treh dneh. Potreboval sem približno dve uri, da sem ugotovil. Dve uri pozneje sem že pisal kodo v produkciji. Približno teden dni kasneje je šel naravnost v proizvodnjo in odšel.

Posledično je videti takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Tukaj je veliko. OpenResty je sestavil kup modulov, tako luash kot engins. In vse imate pripravljeno – razporejeno in deluje.

Primeri

Dovolj besedila, pojdimo k kodi. Tukaj je kratek pozdrav, svet:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Kaj je tam? to je lokacija motorjev. Ne skrbimo, ne pišemo svoje usmerjanja, ne vzamemo nekaj že pripravljenega - že imamo v NGINX, živimo dobro in leno.

content_by_lua_block je blok, ki pravi, da vsebino strežemo s skriptom Lua. Vzamemo spremenljivko motorjev remote_addr in ga potisnite v string.format. To je enako kot sprintf, samo v Lui, samo pravilno. In ga damo stranki.

Posledično bo videti takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Toda nazaj v resnični svet. V proizvodnji nihče ne uporablja Hello World. Naša aplikacija gre običajno v bazo ali kam drugam in največkrat čaka na odgovor.

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Samo sedi in čaka. Ni zelo dobro. Ko pride 100.000 uporabnikov, nam je zelo težko. Zato za primer uporabimo preprosto aplikacijo. Iskali bomo slike, na primer mačke. Le da ne bomo samo iskali, temveč bomo razširili ključne besede in, če je uporabnik iskal »mačke«, bomo našli mačke, puhaste ipd. Najprej moramo pridobiti podatke o zahtevi na zaledju. Videti je takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Dve vrstici vam omogočata, da poberete parametre GET, brez zapletov. Nato te informacije na primer pridobimo iz baze podatkov s tabelo po ključnih besedah ​​in razširitvah z običajno poizvedbo SQL. Vse je preprosto. Videti je takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Knjižnico povezujemo resty.mysql, ki ga že imamo v kompletu. Ničesar nam ni treba namestiti, vse je pripravljeno. Določite, kako vzpostaviti povezavo in narediti poizvedbo SQL:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Malo je strašljivo, a deluje. Tukaj je 10 meja. Izvlečemo 10 plošč, leni smo, nočemo pokazati več. Pri SQL sem pozabil na omejitev.

Nato najdemo slike za vse poizvedbe. Zberemo kup zahtev in izpolnimo tabelo Lua, imenovano reqs, in naredite ngx.location.capture_multi.

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Vse te zahteve gredo vzporedno, odgovori pa se nam vračajo. Čas delovanja je enak odzivnemu času najpočasnejšega. Če vsi ustrelimo nazaj v 50 milisekundah in smo poslali sto zahtev, potem bomo prejeli odgovor v 50 milisekundah.

Ker smo leni in ne želimo pisati obdelave HTTP in predpomnjenja, bomo poskrbeli, da bo NGINX naredil vse namesto nas. Kot ste videli, je bila zahteva za url/fetch, tukaj je:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Naredimo preprosto proxy_pass, določimo, kje predpomniti, kako to narediti, in vse nam deluje.

A to ni dovolj, podatke moramo še dati uporabniku. Najenostavnejša ideja je serializirati vse v JSON, enostavno, v dveh vrsticah. Damo Content-Type, damo JSON.

Vendar obstaja ena težava: uporabnik ne želi brati JSON. Moramo privabiti front-end razvijalce. Včasih se nam sprva ne da. Da, in strokovnjaki za SEO bodo rekli, da če iščemo slike, jim je vseeno. In če jim damo nekaj vsebine, bodo rekli, da naši iskalniki ničesar ne indeksirajo.

Kaj storiti z njim? Seveda bomo uporabniku dali HTML. Generiranje z ročaji ni comme il faut, zato želimo uporabiti predloge. Za to obstaja knjižnica lua-resty-template.

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Zagotovo ste videli tri strašne črke OPM. OpenResty ima lastnega upravitelja paketov, prek katerega lahko namestite kup različnih modulov, zlasti lua-resty-template. Je preprost mehanizem predlog, podoben predlogam Django. Tam lahko pišete kodo in izvajate zamenjavo spremenljivk.

Posledično bo vse videti nekako takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Podatke smo vzeli in ponovno upodobili predlogo v dveh vrsticah. Uporabnik je zadovoljen, dobil je mačke. Ker smo razširili povpraševanje, je dobil tudi medulja za mačje mladiče. Nikoli ne veš, morda ga je iskal, a svoje zahteve ni znal pravilno oblikovati.

Vse je kul, vendar smo v razvoju in še ne želimo pokazati uporabnikom. Naredimo avtorizacijo. Da bi to naredili, poglejmo, kako NGINX obravnava zahtevo v smislu OpenResty:

  • Prva faza - dostop, ko je uporabnik šele prišel, pa smo ga gledali po glavah, po IP naslovu, po drugih podatkih. Lahko ga takoj odrežete, če nam ni všeč. To lahko uporabimo za avtorizacijo ali če prejmemo veliko zahtev, jih v tej fazi enostavno sekamo.
  • reportaža. Ponovno pisanje nekaterih podatkov zahteve.
  • vsebina. Uporabniku dajemo vsebino.
  • filter glave. Spremenite glave odgovorov. Če smo uporabili proxy_pass, lahko prepišemo nekatere glave, preden jih damo uporabniku.
  • telesni filter. Telo lahko spremenimo.
  • prijavi - sečnja. V elasticsearch je mogoče pisati dnevnike brez dodatne plasti.

Naše pooblastilo bo videti nekako takole:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

To bomo dodali k temu location, ki smo ga opisali prej, in tja vstavite naslednjo kodo:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Pogledamo, ali imamo žeton za piškotek. Če ne, potem vržemo avtorizacijo. Uporabniki so zviti in lahko ugibajo, da je treba nastaviti žeton piškotka. Zato ga bomo dali tudi v Redis:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Koda za delo z Redisom je zelo preprosta in se ne razlikuje od drugih jezikov. Hkrati vsi vhodi / izhodi, kaj je tam, kaj je tukaj, ne blokirajo. Če pišete sinhrono kodo, potem deluje asinhrono. Tako kot pri geventu, samo dobro.

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Naredimo samo avtorizacijo:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Pravimo, da moramo prebrati telo zahteve. Prejmemo argumente POST, preverimo, ali sta prijava in geslo pravilna. Če je napačno, vržemo avtorizacijo. In če so pravilni, potem zapišemo žeton v Redis:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Ne pozabite nastaviti piškotka, tudi to se izvede v dveh vrsticah:

OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Primer je preprost, špekulativen. Seveda ne bomo delali servisa, ki bi ljudem razkazoval mačke. A kdo nas pozna. Poglejmo torej, kaj je mogoče narediti v proizvodnji.

  • Minimalistično zaledje. Včasih moramo zaledju izdati kar nekaj podatkov: nekje moramo zamenjati datum, nekje moramo prikazati nekakšen seznam, povedati, koliko uporabnikov je trenutno na spletnem mestu, priviti števec ali statistiko. Nekaj ​​tako majhnega. Nekaj ​​minimalnih kosov je mogoče narediti zelo enostavno. To bo hitro, enostavno in odlično.
  • Predobdelava podatkov. Včasih želimo v svojo stran vdelati oglase in te oglase sprejmemo z zahtevami API-ja. Tukaj je to zelo enostavno narediti. Ne nalagamo našega zaledja, ki že pridno dela. Tukaj lahko prevzamete in prevzamete. Lahko oblikujemo kakšen JS ali, nasprotno, nekaj odlepimo, predhodno obdelamo, preden to damo uporabniku.
  • Fasada za mikroservis. Tudi to je zelo dober primer, implementiral sem ga. Pred tem sem delal v Tenzorju, podjetju za elektronsko poročanje, ki poroča približno polovici pravnih oseb v državi. Naredili smo storitev, tam se marsikaj dela z istim mehanizmom: usmerjanje, avtorizacija in drugo.
    OpenResty lahko uporabite kot lepilo za vaše mikrostoritve, da zagotovite en sam dostop do vsega in en vmesnik. Ker so mikrostoritve lahko napisane tako, da imate tukaj Node.js, tukaj imate PHP, tukaj imate Python, tukaj je nekaj Erlanga, razumemo, da ne želimo povsod prepisati iste kode. Zato lahko OpenResty priključite na sprednjo stran.

  • Statistika in analitika. Običajno je NGINX na vhodu in vse zahteve gredo skozi njega. Na tem mestu je zelo priročno zbirati. Lahko takoj nekaj izračunate in vržete nekam, na primer isti Elasticsearch, Logstash, ali pa preprosto zapišete v dnevnik in nato nekam pošljete.
  • Večuporabniški sistemi. Zelo dobre so na primer tudi spletne igre. Alexander Gladysh vam bo danes v Cape Townu povedal, kako hitro narediti prototip igre za več igralcev z uporabo OpenResty.
  • Filtriranje zahtev (WAF). Zdaj je moderno izdelovati vse vrste požarnih zidov za spletne aplikacije, obstaja veliko storitev, ki jih ponujajo. S pomočjo OpenResty si lahko naredite požarni zid spletne aplikacije, ki bo preprosto in enostavno filtriral zahteve glede na vaše zahteve. Če imate Python, potem razumete, da vam PHP zagotovo ne bo vbrizgan, razen če ga seveda ne ustvarite kjer koli iz konzole. Veste, da imate MySQL in Python. Verjetno lahko tukaj poskusijo narediti nekakšno prečkanje imenika in nekaj vbrizgati v bazo podatkov. Zato lahko neumne zahteve hitro in poceni filtrirate takoj na začetku.
  • Skupnosti. Ker OpenResty temelji na NGINX, ima bonus - to je Skupnost NGINX. Je zelo velik in skupnost NGINX je že odgovorila na veliko vprašanj, ki se vam bodo pojavila na začetku.

    Razvijalci Lua. Včeraj sem se pogovarjal s fanti, ki so prišli na trening HighLoad ++ in slišal, da je samo Tarantool napisan v Lui. To ni tako, veliko stvari je napisanih v Lui. Primeri: OpenResty, strežnik Prosody XMPP, pogon za igre Love2D, Lua je skriptiran v Warcraftu in drugod. Razvijalcev Lua je veliko, imajo veliko in odzivno skupnost. Na vsa moja vprašanja o Lui sem odgovoril v nekaj urah. Ko pišeš na mailing listo, je dobesedno v nekaj minutah že en kup odgovorov, opisujejo kaj in kako, kaj je kaj. Odlično je. Žal tako prijazna iskrena skupnost ni povsod.
    OpenResty ima GitHub, kjer lahko odprete problem, če se kaj pokvari. Obstaja poštni seznam v Google Skupinah, kjer lahko razpravljate o splošnih vprašanjih, obstaja poštni seznam v kitajščini - nikoli ne veste, morda ne govorite angleško, vendar znate kitajščino.

Rezultati

  • Upam, da sem lahko povedal, da je OpenResty zelo priročno spletno ogrodje.
  • Ima nizek vstopni prag, saj je koda podobna tisti, ki jo pišemo mi, jezik je precej preprost in minimalističen.
  • Zagotavlja asinhroni I/O brez povratnih klicev, ne bomo imeli rezancev, kot lahko včasih zapišemo v NodeJS.
  • Ima preprosto uvajanje, saj potrebujemo samo NGINX s pravim modulom in našo kodo, in vse takoj deluje.
  • Velika in odzivna skupnost.

Nisem podrobno povedal, kako poteka usmerjanje, izkazalo se je, da je to zelo dolga zgodba.

Спасибо за внимание!


Vladimir Protasov - OpenResty: spreminjanje NGINX v polnopravni aplikacijski strežnik

Vir: www.habr.com

Dodaj komentar