OpenResty: ginagawang isang ganap na server ng application ang NGINX

OpenResty: ginagawang isang ganap na server ng application ang NGINXMuli naming inilalathala ang transcript ng conference report HighLoad++ 2016, na naganap sa Skolkovo malapit sa Moscow noong Nobyembre 7-8 noong nakaraang taon. Vladimir Protasov nagpapaliwanag kung paano i-extend ang NGINX functionality sa OpenResty at Lua.

Kumusta sa lahat, ang pangalan ko ay Vladimir Protasov, nagtatrabaho ako sa Parallels. Magsasabi ako ng kaunti tungkol sa aking sarili. Ginugugol ko ang tatlong quarter ng buhay ko sa pagsusulat ng code. Ako ay naging isang programmer sa kaibuturan sa literal na kahulugan: minsan nakikita ko ang code sa aking mga panaginip. Ang isang quarter ng buhay ay pang-industriya na pag-unlad, pagsulat ng code na diretso sa produksyon. Isang code na ginagamit ng ilan sa inyo ngunit hindi ito napapansin.

Kaya naiintindihan mo kung gaano ito kahirap. Noong ako ay isang maliit na junior, dumating ako at binigyan ang dalawang-terabyte na database na ito. Ito ay mataas na load para sa lahat ng tao dito ngayon. Pumunta ako sa mga kumperensya at nagtanong: "Guys, sabihin mo sa akin, mayroon kang malaking data, cool ba ang lahat? Ilang base ang mayroon ka doon? Sinagot nila ako: "Mayroon kaming 100 gigabytes!" Sabi ko: "Astig, 100 gigabytes!" At iniisip ko sa sarili ko kung paano maingatan ang aking poker face. Sa palagay mo, oo, ang mga lalaki ay cool, at pagkatapos ay babalik ka at pag-usapan ang mga multi-terabyte na database na ito. At ito ay pagiging isang junior. Naiisip mo ba kung anong suntok ito?

Alam ko ang higit sa 20 programming language. Ito ay isang bagay na kailangan kong malaman habang ako ay nagtatrabaho. Binibigyan ka nila ng code sa Erlang, C, C++, Lua, Python, Ruby, iba pa, at kailangan mong putulin ang lahat. Sa pangkalahatan, kailangan ko. Hindi posible na kalkulahin ang eksaktong numero, ngunit sa isang lugar sa paligid ng ika-20 ang numero ay nawala.

Dahil alam ng lahat ng naroroon kung ano ang Parallels at kung ano ang ginagawa namin, hindi ko sasabihin kung gaano kami ka-cool at kung ano ang ginagawa namin. Sasabihin ko lang sa iyo na mayroon kaming 13 opisina sa buong mundo, higit sa 300 empleyado, development sa Moscow, Tallinn at Malta. Kung gusto mo, maaari mo itong kunin at lumipat sa Malta kung malamig sa taglamig at kailangan mong magpainit ng iyong likod.

Sa partikular, nagsusulat ang aming departamento sa Python 2. Nasa negosyo kami at walang oras upang ipatupad ang mga naka-istilong teknolohiya, kaya nagdurusa kami. Ginagamit namin ang Django dahil mayroon itong lahat, at kinuha namin ang hindi kailangan at itinapon ito. Gayundin ang MySQL, Redis at NGINX. Mayroon din kaming maraming iba pang mga cool na bagay. Mayroon kaming MongoDB, mayroon kaming mga kuneho na tumatakbo, mayroon kaming lahat - ngunit hindi ito sa akin, at hindi ko ito ginagawa.

OpenResty

Sinabi ko ang tungkol sa aking sarili. Alamin natin kung ano ang pag-uusapan ko ngayon:

  • Ano ang OpenResty at ano ang kinakain nito?
  • Bakit muling mag-imbento ng isa pang gulong kung mayroon tayong Python, NodeJS, PHP, Go at iba pang mga cool na bagay na ikinatutuwa ng lahat?
  • At ilang mga halimbawa mula sa buhay. Kinailangan kong i-cut nang husto ang ulat dahil inabot ako ng 3,5 oras, kaya kakaunti ang mga halimbawa.

Ang OpenResty ay NGINX. Salamat sa kanya, mayroon kaming ganap na web server na mahusay ang pagkakasulat at mabilis na gumagana. Sa tingin ko karamihan sa atin ay gumagamit ng NGINX sa produksyon. Alam mong lahat siya ay mabilis at cool. Gumawa sila ng cool na kasabay na I/O dito, kaya hindi namin kailangang mag-cycle ng anuman, tulad ng ginawa nila sa Python. Ang Gevent ay cool, mahusay, ngunit kung sumulat ka ng C code at may mali, pagkatapos ay sa Gevent mabaliw ka sa pagde-debug nito. Nagkaroon ako ng karanasan: tumagal ng dalawang buong araw para malaman kung ano ang nangyari doon. Kung ang isang tao ay hindi naghukay sa paligid ng ilang linggo, natagpuan ang problema, nagsulat sa Internet, at hindi ito natagpuan ng Google, kung gayon kami ay tuluyang nabaliw.

Ang NGINX ay mayroon nang caching at static na nilalaman na tapos na. Hindi mo kailangang mag-alala tungkol sa kung paano ito gagawin nang makatao, para hindi ka bumagal sa isang lugar, para hindi ka mawalan ng mga deskriptor sa isang lugar. Ang Nginx ay napaka-maginhawang i-deploy, hindi mo kailangang isipin kung ano ang dapat gawin - WSGI, PHP-FPM, Gunicorn, Unicorn. Naka-install ang Nginx, ibinigay sa mga admin, alam nila kung paano ito gagawin. Pinoproseso ng Nginx ang mga kahilingan sa isang structured na paraan. Pag-uusapan ko ito mamaya. Sa madaling salita, mayroon itong yugto kapag tinanggap lang nito ang kahilingan, kapag naproseso ito, at kapag inihatid nito ang nilalaman sa user.

Ang Nginx ay cool, ngunit may isang problema: ito ay hindi sapat na kakayahang umangkop, kahit na sa lahat ng mga cool na tampok na ang mga guys ay crammed sa config, sa kabila ng katotohanan na ito ay maaaring i-configure. Ang kapangyarihang ito ay hindi sapat. Iyon ang dahilan kung bakit ang mga lalaki mula sa Taobao, isang mahabang panahon ang nakalipas, tila walong taon na ang nakalipas, binuo si Lua dito. Ano ang ibinibigay nito?

  • Laki. Ito ay maliit. Nagbibigay ang LuaJIT ng humigit-kumulang 100-200 kilobytes ng memory overhead at minimal na performance overhead.
  • bilis. Ang interpreter ng LuaJIT ay malapit sa C sa maraming mga sitwasyon, sa ilang mga sitwasyon ay natatalo ito sa Java, sa iba ay nahihigitan nito. Sa loob ng ilang panahon ito ay itinuturing na estado ng sining, ang pinakaastig na JIT compiler. Ngayon ay may mga mas malamig, ngunit ang mga ito ay napakabigat, halimbawa, ang parehong V8. Ang ilang mga JS interpreter at Java HotSpot ay mas mabilis sa ilang mga punto, ngunit sa ilang mga lugar ay natatalo pa rin sila.
  • Madaling matutunan. Kung mayroon kang, halimbawa, isang Perl code base, at hindi ka nagbu-book, hindi ka makakahanap ng mga Perl programmer. Dahil wala sila, lahat sila ay inalis, at ang pagtuturo sa kanila ay mahaba at mahirap. Kung gusto mo ng mga programmer para sa ibang bagay, maaaring kailanganin mo rin silang sanayin muli o hanapin sila. Sa kaso ni Lua, ang lahat ay simple. Ang sinumang junior ay maaaring matuto ng Lua sa loob ng tatlong araw. Inabot ako ng halos dalawang oras para malaman ito. Pagkalipas ng dalawang oras ay nagsusulat na ako ng code sa produksyon. Makalipas ang halos isang linggo dumiretso siya sa production at umalis.

Bilang resulta, ganito ang hitsura:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Marami dito. Ang OpenResty ay nakakolekta ng isang grupo ng mga module, parehong luash at mga engine. At handa na ang lahat - na-deploy at gumagana.

Mga halimbawa

Sapat na ang lyrics, lumipat tayo sa code. Narito ang isang maliit na Hello World:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Anong meron? Ito ay isang lokasyon ng Engins. Hindi kami nag-aalala, hindi kami nagsusulat ng aming sariling ruta, hindi kami kumukuha ng isang handa na - mayroon na kami nito sa NGINX, nabubuhay kami ng mabuti at tamad na buhay.

content_by_lua_block ay isang bloke na nagsasabing naghahatid kami ng nilalaman gamit ang isang script ng Lua. Kinukuha namin ang variable ng Engins remote_addr at ilagay ito string.format. Ito ay katulad ng sprintf, sa Lua lang, tama lang. At ibinibigay namin ito sa kliyente.

Bilang resulta, magiging ganito ang hitsura:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Pero balik tayo sa totoong mundo. Walang nag-deploy ng Hello World sa produksyon. Karaniwang napupunta ang aming application sa database o sa ibang lugar at kadalasan ay naghihintay ng tugon.

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Nakaupo lang siya at naghihintay. Hindi ito masyadong maganda. Kapag dumating ang 100.000 user, napakahirap para sa amin. Kaya't gumamit tayo ng isang simpleng application bilang isang halimbawa. Maghahanap kami ng mga larawan, halimbawa, ng mga pusa. Ngunit hindi lang kami maghahanap, palalawakin namin ang mga keyword at, kung naghanap ang user ng "mga kuting," makakahanap kami ng mga pusa, mabalahibong pusa, at iba pa. Una, kailangan nating makuha ang data ng kahilingan sa backend. Mukhang ganito:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Binibigyang-daan ka ng dalawang linya na kunin ang mga parameter ng GET, walang komplikasyon. Susunod, sabihin nating, mula sa isang database na may sign para sa isang keyword at extension, nakukuha namin ang impormasyong ito gamit ang isang regular na query sa SQL. Simple lang. Mukhang ganito:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Pagkonekta sa library resty.mysql, na mayroon na tayo sa kit. Hindi namin kailangang mag-install ng anuman, handa na ang lahat. Ipinapahiwatig namin kung paano kumonekta at gumawa ng SQL query:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Medyo nakakatakot dito, pero gumagana ang lahat. Narito ang 10 ay ang limitasyon. We pull out 10 entries, tinatamad kami, ayaw na naming magpakita pa. Nakalimutan ko ang tungkol sa limitasyon sa SQL.

Susunod na mahanap namin ang mga larawan para sa lahat ng mga query. Kinokolekta namin ang isang grupo ng mga kahilingan at pinupunan ang isang Lua table na tinatawag reqs, at ginagawa namin ngx.location.capture_multi.

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Ang lahat ng mga kahilingang ito ay ipinadala nang magkatulad, at ang mga sagot ay ibinabalik sa amin. Ang oras ng pagpapatakbo ay katumbas ng oras ng pagtugon ng pinakamabagal. Kung mag-shoot kaming lahat sa loob ng 50 millisecond, at nagpadala kami ng isang daang kahilingan, makakatanggap kami ng sagot sa loob ng 50 millisecond.

Dahil tinatamad kami at ayaw magsulat ng HTTP at paghawak ng cache, gagawin namin ang NGINX para sa amin. Tulad ng nakita mo, mayroong isang kahilingan para sa url/fetch, narito siya:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Ginagawa namin itong simple proxy_pass, ipinapahiwatig namin kung saan i-cache, kung paano ito gagawin, at lahat ay gumagana para sa amin.

Ngunit ito ay hindi sapat, kailangan pa rin nating ibigay ang data sa gumagamit. Ang pinakasimpleng ideya ay i-serialize ang lahat sa JSON, nang madali, sa dalawang linya. Nagbibigay kami ng Uri ng Nilalaman, binibigyan namin ang JSON.

Ngunit may isang kahirapan: ayaw basahin ng user ang JSON. Kailangan nating makaakit ng mga front-end na developer. Minsan ayaw nating gawin ito sa una. At sasabihin ng mga espesyalista sa SEO na kung naghahanap tayo ng mga larawan, hindi ito mahalaga sa kanila. At kung bibigyan namin sila ng ilang nilalaman, sasabihin nila na ang aming mga search engine ay hindi nag-index ng anuman.

Ano ang gagawin tungkol dito? Siyempre, bibigyan namin ang user ng HTML. Ang pagbuo sa pamamagitan ng kamay ay hindi comme il faut, kaya gusto naming gumamit ng mga template. May library para dito lua-resty-template.

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Marahil ay nakita mo na ang tatlong nakakatakot na letrang OPM. Ang OpenResty ay may sarili nitong manager ng package, kung saan maaari kang mag-install ng isang grupo ng iba't ibang mga module, sa partikular, lua-resty-template. Ito ay isang simpleng template engine, katulad ng mga template ng Django. Doon maaari kang magsulat ng code at magsagawa ng variable substitution.

Bilang isang resulta, ang lahat ay magiging ganito:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Kinuha namin ang data at nai-render ang template, muli sa dalawang linya. Ang gumagamit ay masaya, nakatanggap siya ng mga pusa. Dahil pinalawak namin ang kahilingan, nakatanggap din siya ng fur seal para sa mga kuting. Hindi mo alam, marahil ay eksaktong hinahanap niya ito, ngunit hindi mabalangkas nang tama ang kanyang kahilingan.

Ang lahat ay cool, ngunit kami ay nasa pagbuo at ayaw pa naming ipakita ito sa mga user. Gawin natin ang authorization. Upang gawin ito, tingnan natin kung paano pinangangasiwaan ng NGINX ang kahilingan sa mga termino ng OpenResty:

  • Unang bahagi - daan, noong kadadating lang ng user, at tiningnan namin siya sa pamamagitan ng mga header, sa pamamagitan ng IP address, at ng iba pang data. Maaari natin itong putulin kaagad kung hindi natin ito gusto. Magagamit ito para sa awtorisasyon, o kung makatanggap kami ng maraming kahilingan, madali naming mapuputol ang mga ito sa yugtong ito.
  • pagsulat na muli. Sinusulat namin muli ang ilang data ng kahilingan.
  • nilalaman. Inihahatid namin ang nilalaman sa gumagamit.
  • filter ng mga header. Pinapalitan namin ang mga header ng tugon. Kung ginamit natin proxy_pass, maaari naming muling isulat ang ilang mga header bago ito ibigay sa user.
  • filter ng katawan. Maaari nating baguhin ang katawan.
  • mag-log - pagtotroso. Maaari kang magsulat ng mga log sa elasticsearch nang walang karagdagang layer.

Magiging ganito ang hitsura ng aming awtorisasyon:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Idagdag namin ito sa isang iyon location, na inilarawan namin dati, at ilagay ang sumusunod na code doon:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Tinitingnan namin kung mayroon kaming cookie token. Kung hindi, humihingi kami ng pahintulot. Ang mga gumagamit ay tuso at maaaring hulaan na kailangan nilang magtakda ng cookie token. Samakatuwid, ilalagay din namin ito sa Redis:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Ang code para sa pagtatrabaho sa Redis ay napaka-simple at hindi naiiba sa ibang mga wika. Kasabay nito, ang lahat ng input/output, dito at doon, ay hindi humaharang. Kung sumulat ka ng kasabay na code, ito ay gumagana nang asynchronously. Halos tulad ng gevent, ngunit nagawa nang maayos.

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Gawin natin ang awtorisasyon mismo:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Sinasabi namin na kailangan naming basahin ang katawan ng kahilingan. Nakatanggap kami ng mga argumento ng POST at suriin kung tama ang login at password. Kung mali ang mga ito, hinahamon ka namin para sa pahintulot. At kung tama, pagkatapos ay isulat ang token sa Redis:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Huwag kalimutang itakda ang cookie, ginagawa din ito sa dalawang linya:

OpenResty: ginagawang isang ganap na server ng application ang NGINX

Ang halimbawa ay simple at haka-haka. Siyempre, hindi kami gagawa ng serbisyo na nagpapakita ng mga pusa sa mga tao. Ngunit sino ang nakakakilala sa amin. Kaya't tingnan natin kung ano ang maaaring gawin sa produksyon.

  • Minimalistic na backend. Minsan kailangan nating mag-output ng kaunting data lang sa backend: sa isang lugar kailangan nating maglagay ng petsa, sa isang lugar na kailangan nating magpakita ng listahan, sabihin kung gaano karaming user ang nasa site ngayon, mag-attach ng counter o istatistika. Isang bagay na napakaliit. Ang ilang mga kaunting piraso ay maaaring gawin nang napakadali. Gagawin nitong mabilis, madali at mahusay.
  • Preprocessing ng data. Minsan gusto naming i-embed ang advertising sa aming page, at natatanggap namin ang advertising na ito gamit ang mga kahilingan sa API. Ito ay napakadaling gawin dito. Hindi namin nilo-load ang aming backend, na nakaupo na at nagsusumikap. Maaari mo itong kunin at kolektahin dito. Maaari naming pagsama-samahin ang ilang JS o, sa kabilang banda, i-uncouple ito at iproseso ang isang bagay bago ito ibigay sa user.
  • Facade para sa microservice. Ito rin ay isang napakahusay na kaso, ipinatupad ko ito. Bago iyon, nagtrabaho ako sa Tenzor, isang kumpanya na tumatalakay sa elektronikong pag-uulat at nagbibigay ng pag-uulat sa humigit-kumulang kalahati ng mga legal na entity sa bansa. Gumawa kami ng serbisyo, maraming bagay ang ginawa doon gamit ang parehong mekanismo: pagruruta, awtorisasyon at higit pa.
    Maaaring gamitin ang OpenResty bilang pandikit para sa iyong mga microservice, na nagbibigay ng isang access sa lahat at isang interface. Dahil ang mga microservice ay maaaring isulat sa paraang mayroon kang Node.js dito, PHP dito, Python dito, ilang bagay na Erlang dito, naiintindihan namin na hindi namin nais na muling isulat ang parehong code sa lahat ng dako. Samakatuwid, ang OpenResty ay maaaring isaksak sa harap.

  • Mga istatistika at analytics. Karaniwan ang NGINX ay nasa pasukan, at lahat ng mga kahilingan ay dumaan dito. Ito ay sa lugar na ito na ito ay napaka-maginhawa upang mangolekta. Maaari mong agad na kalkulahin ang isang bagay at i-upload ito sa isang lugar, halimbawa, Elasticsearch, Logstash, o isulat lang ito sa log at pagkatapos ay ipadala ito sa isang lugar.
  • Multi-user system. Halimbawa, ang mga online na laro ay napakahusay ding gawin. Ngayon sa Cape Town, magsasalita si Alexander Gladysh tungkol sa kung paano mabilis na magprototype ng multiplayer na laro gamit ang OpenResty.
  • Pag-filter ng Kahilingan (WAF). Sa ngayon, naka-istilong gumawa ng lahat ng uri ng mga firewall ng web application; maraming serbisyo ang nagbibigay sa kanila. Gamit ang OpenResty, maaari mong gawing firewall ang iyong sarili sa web application na simple at madaling mag-filter ng mga kahilingan ayon sa iyong mga kinakailangan. Kung mayroon kang Python, naiintindihan mo na ang PHP ay tiyak na hindi mai-inject sa iyo, maliban kung, siyempre, i-spawn mo ito kahit saan mula sa console. Alam mong mayroon kang MySQL at Python. Marahil, maaari nilang subukang gumawa ng ilang uri ng direktoryo na traversal at mag-inject ng isang bagay sa database. Samakatuwid, maaari mong i-filter ang mga kakaibang query nang mabilis at mura sa harap mismo.
  • Komunidad Dahil ang OpenResty ay binuo sa NGINX, mayroon itong bonus - ito komunidad ng NGINX. Napakalaki nito, at isang disenteng bahagi ng mga tanong na magkakaroon ka sa una ay nalutas na ng komunidad ng NGINX.

    Mga developer ng Lua. Kahapon ay nakipag-usap ako sa mga lalaki na dumating sa araw ng pagsasanay sa HighLoad++ at narinig ko na Tarantool lang ang nakasulat sa Lua. Hindi ito totoo, maraming bagay ang nakasulat sa Lua. Mga halimbawa: OpenResty, Prosody XMPP server, Love2D game engine, Lua scripted sa Warcraft at sa ibang lugar. Mayroong maraming mga developer ng Lua, mayroon silang isang malaki at tumutugon na komunidad. Lahat ng tanong ko sa Lua ay nalutas sa loob ng ilang oras. Kapag sumulat ka sa mailing list, literal sa loob ng ilang minuto ay marami nang mga tugon, na naglalarawan kung ano at paano, ano. Ang galing. Sa kasamaang palad, ang ganitong uri, espirituwal na komunidad ay wala sa lahat ng dako.
    Mayroong GitHub para sa OpenResty, kung saan maaari kang magbukas ng isyu kung may sira. Mayroong mailing list sa Google Groups, kung saan maaari mong talakayin ang mga pangkalahatang isyu, mayroong mailing list sa Chinese - hindi mo alam, marahil hindi ka nagsasalita ng Ingles, ngunit alam mo ang Chinese.

Mga resulta ng

  • Umaasa ako na naihatid ko na ang OpenResty ay isang napaka-kumbinyenteng framework na iniayon para sa web.
  • Ito ay may mababang hadlang sa pagpasok, dahil ang code ay katulad ng kung ano ang isinusulat namin, ang wika ay medyo simple at minimalistic.
  • Nagbibigay ito ng asynchronous na I/O na walang mga callback, wala kaming anumang pansit na maaari naming isulat minsan sa NodeJS.
  • Ito ay may madaling pag-deploy, dahil kailangan lang namin ng NGINX kasama ang kinakailangang module at ang aming code, at lahat ay gumagana kaagad.
  • Malaki at tumutugon na komunidad.

Hindi ko sinabi nang detalyado kung paano ginagawa ang pagruruta, ito ay naging isang napakahabang kuwento.

Salamat sa iyo!


Vladimir Protasov - OpenResty: ginagawang isang ganap na server ng application ang NGINX

Pinagmulan: www.habr.com

Magdagdag ng komento