Ni denove publikigas la transskribon de la konferenca raporto 2016, kiu okazis en Skolkovo apud Moskvo la 7-8-an de novembro pasintjare. klarigas kiel etendi NGINX-funkciecon kun OpenResty kaj Lua.
Saluton al ĉiuj, mia nomo estas Vladimir Protasov, mi laboras ĉe Parallels. Mi rakontos al vi iom pri mi mem. Mi pasigas tri kvaronojn de mia vivo skribante kodon. Mi fariĝis programisto ĝis la kerno en la laŭvorta senco: foje mi vidas kodon en miaj sonĝoj. Kvarono de la vivo estas industria evoluo, skribanta kodon kiu iras rekte en produktadon. Kodo, kiun iuj el vi uzas sed ne rimarkas ĝin.
Do vi komprenas kiom malbona ĝi estis. Kiam mi estis iom juna, mi venis kaj ricevis ĉi tiujn du-terabajtajn datumbazojn. Ĝi estas alta ŝarĝo por ĉiuj ĉi tie nun. Mi iris al konferencoj kaj demandis: "Knaboj, diru al mi, vi havas grandajn datumojn, ĉu ĉio estas bonega? Kiom da bazoj vi havas tie? Ili respondis al mi: "Ni havas 100 gigabajtojn!" Mi diris: "Bone, 100 gigabajtoj!" Kaj mi pensis al mi kiel zorge konservi mian pokervizaĝon. Vi pensas, jes, la uloj estas bonegaj, kaj tiam vi reiras kaj tuŝas ĉi tiujn mult-terabajtajn datumbazojn. Kaj ĉi tio estas esti junulo. Ĉu vi povas imagi, kia bato estas ĉi tio?
Mi konas pli ol 20 programlingvojn. Ĉi tio estas io, kion mi devis eltrovi dum mi laboris. Ili donas al vi kodon en Erlang, C, C++, Lua, Python, Ruby, io alia, kaj vi devas tranĉi ĉion. Ĝenerale, mi devis. Ne eblis kalkuli la precizan nombron, sed ie ĉirkaŭ la 20-a la nombro perdiĝis.
Ĉar ĉiuj ĉeestantoj scias kio estas Parallels kaj kion ni faras, mi ne parolos pri kiom mojosa ni estas kaj kion ni faras. Mi nur diros al vi, ke ni havas 13 oficejojn tra la mondo, pli ol 300 dungitojn, disvolviĝon en Moskvo, Talino kaj Malto. Se vi deziras, vi povas preni ĝin kaj translokiĝi al Malto se estas malvarme vintre kaj vi bezonas varmigi vian dorson.
Specife, nia fako skribas en Python 2. Ni estas en komerco kaj ne havas tempon por efektivigi modajn teknologiojn, do ni suferas. Ni uzas Django ĉar ĝi havas ĉion, kaj ni prenis kio estis nenecesa kaj forĵetis ĝin. Ankaŭ MySQL, Redis kaj NGINX. Ni ankaŭ havas multajn aliajn bonegajn aferojn. Ni havas MongoDB, ni havas kuniklojn, ni havas ĉion - sed ĝi ne estas mia, kaj mi ne faras ĝin.
OpenResty
Mi rakontis pri mi mem. Ni eltrovu, pri kio mi parolos hodiaŭ:
- Kio estas OpenResty kaj per kio ĝi estas manĝata?
- Kial reinventi alian radon kiam ni havas Python, NodeJS, PHP, Go kaj aliajn bonegajn aferojn, pri kiuj ĉiuj ĝojas?
- Kaj kelkaj ekzemploj el la vivo. Mi devis multe tranĉi la raporton ĉar mi daŭris 3,5 horojn, do estos malmultaj ekzemploj.
OpenResty estas NGINX. Danke al li, ni havas plenrajtan retservilon kiu estas bone verkita kaj funkcias rapide. Mi pensas, ke la plimulto el ni uzas NGINX en produktado. Vi ĉiuj scias, ke li estas rapida kaj mojosa. Ili faris bonegan sinkronan I/O en ĝi, do ni ne bezonas bicikli ion ajn, same kiel ili faris en Python. Gevent estas bonega, bonega, sed se vi skribas C-kodon kaj io misfunkcias, tiam kun Gevent vi freneziĝos sencimigi ĝin. Mi havis la sperton: necesis du tutaj tagoj por eltrovi kio misfunkciis tie. Se iu ne fosus ĉirkaŭe dum kelkaj semajnoj, trovus la problemon, skribus en Interreto, kaj Guglo ne trovus ĝin, tiam ni tute frenezus.
NGINX jam havas kaŝmemoron kaj statikan enhavon farita. Vi ne bezonas zorgi pri kiel fari tion home, por ke vi ne malrapidu ie, por ke vi ne perdu priskribilojn ie. Nginx estas tre oportuna por disfaldi, vi ne bezonas pensi pri kion preni - WSGI, PHP-FPM, Gunicorn, Unicorn. Nginx estis instalita, donita al la administrantoj, ili scias kiel labori kun ĝi. Nginx prilaboras petojn en strukturita maniero. Mi parolos pri tio iom poste. Resume, ĝi havas fazon kiam ĝi ĵus akceptis la peton, kiam ĝi prilaboris ĝin, kaj kiam ĝi servis la enhavon al la uzanto.
Nginx estas bonega, sed estas unu problemo: ĝi ne estas sufiĉe fleksebla, eĉ kun ĉiuj bonegaj funkcioj, kiujn la uloj enŝtopis en la agordon, malgraŭ tio, kio povas esti agordita. Ĉi tiu potenco ne sufiĉas. Tial la uloj el Taobao, antaŭ longe, ŝajnas, ke antaŭ ok jaroj, enkonstruis Luan en ĝin. Kion ĝi donas?
- grandeco. Ĝi estas malgranda. LuaJIT donas ĉirkaŭ 100-200 kilobajtojn da memoro superkoste kaj minimuman rendimenton superkoste.
- Rapido. La LuaJIT-interpretisto estas proksima al C en multaj situacioj, en iuj situacioj ĝi perdas kontraŭ Java, en aliaj ĝi superas ĝin. Dum iom da tempo ĝi estis konsiderita la stato de arto, la plej bonega JIT-kompililo. Nun estas pli malvarmaj, sed ili estas tre pezaj, ekzemple la sama V8. Kelkaj JS-interpretistoj kaj Java HotSpot estas pli rapidaj en iuj punktoj, sed en kelkaj lokoj ili ankoraŭ malgajnas.
- Facile lernebla. Se vi havas, ekzemple, Perl-kodbazon, kaj vi ne Rezervas, vi ne trovos Perl-programistojn. Ĉar ili ne ekzistas, ili ĉiuj estis forprenitaj, kaj instrui ilin estas longa kaj malfacila. Se vi volas programistojn por io alia, vi eble ankaŭ devos retrejni ilin aŭ trovi ilin. En la kazo de Lua, ĉio estas simpla. Ajna junulo povas lerni Lua en tri tagoj. Mi bezonis ĉirkaŭ du horojn por eltrovi ĝin. Du horojn poste mi jam skribis kodon en produktado. Proksimume semajnon poste li iris rekte al produktado kaj foriris.
Kiel rezulto, ĝi aspektas jene:

Estas multe ĉi tie. OpenResty kolektis amason da moduloj, ambaŭ luash kaj motoroj. Kaj vi havas ĉion preta - deplojita kaj funkcianta.
ekzemploj
Sufiĉe da la kantotekstoj, ni transiru al la kodo. Jen malgranda Saluton Mondo:

Kio estas tie? Ĉi tio estas loko de Engins. Ni ne maltrankviliĝas, ni ne skribas nian propran vojigon, ni ne prenas iun pretan - ni jam havas ĝin en NGINX, ni vivas bonan kaj maldiligentan vivon.
content_by_lua_block estas bloko, kiu diras, ke ni servas enhavon per Lua-skripto. Ni prenas la Engins-variablon remote_addr kaj enmetu ĝin string.format. Ĉi tio estas la sama kiel sprintf, nur en Lua, nur korekta. Kaj ni donas ĝin al la kliento.
Kiel rezulto, ĝi aspektos jene:

Sed ni revenu al la reala mondo. Neniu deplojas Hello World al produktado. Nia aplikaĵo kutime iras al la datumbazo aŭ aliloke kaj plejofte atendas respondon.

Li nur sidas kaj atendas. Ĝi ne estas tre bona. Kiam 100.000 XNUMX uzantoj venas, estas tre malfacile por ni. Do ni uzu simplan aplikaĵon kiel ekzemplon. Ni serĉos bildojn, ekzemple, de katoj. Sed ni ne nur serĉos, ni vastigos la ŝlosilvortojn kaj, se la uzanto serĉis "katidojn", ni trovos katojn, peltajn katojn ktp. Unue, ni devas akiri la petajn datumojn sur la backend. Ĝi aspektas jene:

Du linioj permesas vin preni GET-parametrojn, sen komplikaĵoj. Poste, ni diru, el datumbazo kun signo por ŝlosilvorto kaj etendaĵo, ni akiras ĉi tiun informon uzante regulan SQL-demandon. Ĝi estas simpla. Ĝi aspektas jene:

Konektante la bibliotekon resty.mysql, kiun ni jam havas en la ilaro. Ni ne bezonas instali ion ajn, ĉio estas preta. Ni indikas kiel konekti kaj fari SQL-demandon:

Ĉi tie estas iom timiga, sed ĉio funkcias. Ĉi tie 10 estas la limo. Ni eltiras 10 enskribojn, ni estas maldiligentaj, ni ne volas montri pli. Mi forgesis pri la limo en SQL.
Poste ni trovas bildojn por ĉiuj demandoj. Ni kolektas amason da petoj kaj plenigas Lua-tabelon nomatan reqs, kaj ni faras ngx.location.capture_multi.

Ĉiuj ĉi tiuj petoj estas senditaj paralele, kaj respondoj estas resenditaj al ni. La funkciada tempo estas egala al la responda tempo de la plej malrapida. Se ni ĉiuj pafos en 50 milisekundoj, kaj ni sendis cent petojn, tiam ni ricevos respondon en 50 milisekundoj.
Ĉar ni estas maldiligentaj kaj ne volas skribi HTTP kaj kaŝmemoro-traktadon, ni igos NGINX fari ĉion por ni. Kiel vi vidis, estis peto por url/fetch, jen li:

Ni simpligas ĝin proxy_pass, ni indikas kie kaŝmemori, kiel fari ĝin, kaj ĉio funkcias por ni.
Sed ĉi tio ne sufiĉas, ni ankoraŭ bezonas doni la datumojn al la uzanto. La plej simpla ideo estas seriigi ĉion en JSON, facile, en du linioj. Ni donas Content-Type, ni donas JSON.
Sed estas unu malfacilaĵo: la uzanto ne volas legi JSON. Ni devas altiri antaŭajn programistojn. Kelkfoje ni ne volas fari tion komence. Kaj SEO-specialistoj diros, ke se ni serĉas bildojn, tiam ne gravas por ili. Kaj se ni donos al ili iom da enhavo, ili diros, ke niaj serĉiloj nenion indeksas.
Kion fari pri ĝi? Kompreneble, ni donos al la uzanto HTML. Mane generi ne estas comme il faut, do ni volas uzi ŝablonojn. Estas biblioteko por tio lua-resty-template.

Vi verŝajne vidis la tri timigajn literojn OPM. OpenResty venas kun sia propra pakaĵmanaĝero, per kiu vi povas instali amason da malsamaj moduloj, precipe, lua-resty-template. Ĉi tio estas simpla ŝablonmotoro, simila al Django-ŝablonoj. Tie vi povas skribi kodon kaj fari varian anstataŭigon.
Kiel rezulto, ĉio aspektos kiel ĉi tio:

Ni prenis la datumojn kaj redonis la ŝablonon, denove en du linioj. La uzanto estas feliĉa, li ricevis katojn. Ĉar ni vastigis la peton, li ankaŭ ricevis peltfokon por katidoj. Vi neniam scias, eble li serĉis ĝuste tion, sed ne povis ĝuste formuli sian peton.
Ĉio estas bonega, sed ni estas evoluantaj kaj ankoraŭ ne volas montri ĝin al uzantoj. Ni faru la rajtigon. Por fari tion, ni rigardu kiel NGINX pritraktas la peton laŭ OpenResty-kondiĉoj:
- Unua fazo - aliro, kiam la uzanto ĵus alvenis, kaj ni rigardis lin per kaplinioj, per IP-adreso kaj per aliaj datumoj. Ni povas tuj detranĉi ĝin se ni ne ŝatas ĝin. Ĉi tio povas esti uzata por rajtigo, aŭ se ni ricevas multajn petojn, ni povas facile fortranĉi ilin ĉe ĉi tiu fazo.
- reverki. Ni reverkas kelkajn petajn datumojn.
- enhavo. Ni liveras la enhavon al la uzanto.
- titoloj filtrilo. Ni anstataŭigas la respondajn kapliniojn. Se ni uzis
proxy_pass, ni povas reverki kelkajn kapliniojn antaŭ ol doni ĝin al la uzanto. - korpo filtrilo. Ni povas ŝanĝi la korpon.
- Log — arbohakado. Vi povas skribi protokolojn en elasticsearch sen plia tavolo.
Nia rajtigo aspektos kiel ĉi tio:

Ni aldonos ĉi tion al tiu location, kiun ni priskribis antaŭe, kaj metis la jenan kodon tie:

Ni rigardas por vidi ĉu ni havas kuketon-ĵetonon. Se ne, tiam ni petas rajtigon. Uzantoj estas ruzaj kaj povas diveni, ke ili devas agordi kuketon-ĵetonon. Tial ni ankaŭ metos ĝin en Redis:

La kodo por labori kun Redis estas tre simpla kaj ne diferencas de aliaj lingvoj. Samtempe, ĉio enigo/eligo, ĉi tie kaj tie, ne blokiĝas. Se vi skribas sinkronan kodon, ĝi funkcias nesinkrone. Preskaŭ kiel gevent, sed bone farita.

Ni faru la rajtigon mem:

Ni diras, ke ni devas legi la korpon de la peto. Ni ricevas POST-argumentojn kaj kontrolas, ke la ensaluto kaj pasvorto estas ĝustaj. Se ili estas malĝustaj, tiam ni defias vin pri rajtigo. Kaj se ĝuste, tiam skribu la ĵetonon en Redis:

Ne forgesu agordi la kuketon, ĉi tio ankaŭ estas farita en du linioj:

La ekzemplo estas simpla kaj konjekta. Kompreneble, ni ne faros servon, kiu montras al homoj katojn. Sed kiu konas nin. Do ni iru super kio povas esti farita en produktado.
- Minimalisma backend. Kelkfoje ni bezonas eligi nur iomete da datumoj al la backend: ie ni devas enmeti daton, ie ni devas montri liston, diru kiom da uzantoj nun estas en la retejo, kunsendi nombrilon aŭ statistikon. Io tiel malgranda. Iuj minimumaj pecoj povas esti faritaj tre facile. Ĉi tio faros ĝin rapida, facila kaj bonega.
- Antaŭtraktado de datumoj. Kelkfoje ni volas enmeti reklamadon en nian paĝon, kaj ni ricevas ĉi tiun reklamadon uzante API-petojn. Ĉi tio estas tre facile fari ĉi tie. Ni ne ŝarĝas nian backend, kiu jam sidas kaj laboras forte. Vi povas preni ĝin kaj kolekti ĝin ĉi tie. Ni povas kunmeti iun JS aŭ, male, malkunligi ĝin kaj antaŭprilabori ion antaŭ ol doni ĝin al la uzanto.
- Fasado por mikroservo. Ĉi tio ankaŭ estas tre bona kazo, mi efektivigis ĝin. Antaŭ tio, mi laboris ĉe Tenzor, firmao kiu traktas elektronikan raportadon kaj provizas raportadon al proksimume duono de la juraj entoj en la lando. Ni kreis servon, multaj aferoj estis faritaj tie uzante la saman mekanismon: vojigo, rajtigo kaj pli.
OpenResty povas esti uzata kiel gluaĵo por viaj mikroservoj, provizante ununuran aliron al ĉio kaj ununuran interfacon. Ĉar mikroservoj povas esti skribitaj tiel, ke vi havas Node.js ĉi tie, PHP ĉi tie, Python ĉi tie, iun Erlang-aĵon ĉi tie, ni komprenas, ke ni ne volas reverki la saman kodon ĉie. Tial, OpenResty povas esti ŝtopita en la fronton. - Statistiko kaj analizo. Kutime NGINX estas ĉe la enirejo, kaj ĉiuj petoj trairas ĝin. Estas en ĉi tiu loko, ke estas tre oportune kolekti. Vi povas tuj kalkuli ion kaj alŝuti ĝin ie, ekzemple, Elasticsearch, Logstash, aŭ simple skribi ĝin al la protokolo kaj poste sendi ĝin ien.
- Multi-uzantaj sistemoj. Ekzemple, interretaj ludoj ankaŭ estas tre bonaj por fari. Hodiaŭ en Kab-urbo, Alexander Gladysh parolos pri kiel rapide prototipi plurludantan ludon uzante OpenResty.
- Peto-Filtrado (WAF). Nuntempe estas laŭmode fari ĉiajn retaplikajn fajroŝirmilojn; ekzistas multaj servoj, kiuj provizas ilin. Uzante OpenResty, vi povas fari al vi retaplikaĵan fajroŝirmilon, kiu simple kaj facile filtras petojn laŭ viaj postuloj. Se vi havas Python, tiam vi komprenas, ke PHP certe ne estos injektita en vin, krom se, kompreneble, vi generas ĝin ie ajn de la konzolo. Vi scias, ke vi havas MySQL kaj Python. Verŝajne, ili eble provos fari ian dosierujon trapasadon kaj injekti ion en la datumbazon. Tial vi povas filtri strangajn demandojn rapide kaj malmultekoste rekte ĉe la fronto.
- Komunumo. Ĉar OpenResty estas konstruita sur NGINX, ĝi havas gratifikon - ĉi tio NGINX-komunumo. Ĝi estas tre granda, kaj deca parto de la demandoj, kiujn vi havos komence, jam estis solvita de la komunumo NGINX.
Lua programistoj. Hieraŭ mi parolis kun la uloj kiuj venis al la HighLoad++ trejna tago kaj aŭdis ke nur Tarantool estis skribita en Lua. Tio ne estas vera, multaj aferoj estas skribitaj en Lua. Ekzemploj: OpenResty, Prosody XMPP-servilo, Love2D ludmaŝino, Lua skribita en Warcraft kaj aliloke. Estas multaj Lua-programistoj, ili havas grandan kaj respondeman komunumon. Ĉiuj miaj Lua-demandoj estis solvitaj ene de kelkaj horoj. Kiam vi skribas al la dissendolisto, laŭvorte ene de kelkaj minutoj jam estas amaso da respondoj, priskribante kio kaj kiel, kio estas kio. Ĝi estas bonega. Bedaŭrinde tia afabla, spirita komunumo ne estas ĉie.
Estas GitHub por OpenResty, kie vi povas malfermi problemon se io estas rompita. Estas dissendolisto en Guglo-Grupoj, kie oni povas diskuti ĝeneralajn aferojn, estas dissendolisto en la ĉina - oni neniam scias, eble oni ne parolas la anglan, sed oni ja scipovas la ĉinan.
Rezultoj
- Mi esperas, ke mi povis transdoni, ke OpenResty estas tre oportuna kadro adaptita por la reto.
- Ĝi havas malaltan baron al eniro, ĉar la kodo estas simila al tio, en kiu ni skribas, la lingvo estas sufiĉe simpla kaj minimumisma.
- Ĝi provizas nesinkronan I/O sen revokoj, ni ne havos nudelojn kiel ni foje povas skribi en NodeJS.
- Ĝi havas facilan deplojon, ĉar ni bezonas nur NGINX kun la necesa modulo kaj nia kodo, kaj ĉio funkcias tuj.
- Granda kaj respondema komunumo.
Mi ne rakontis detale kiel enrutado estas farita, ĝi rezultis esti tre longa rakonto.
Спасибо за внимание!

fonto: www.habr.com
