OpenResty: convertir NGINX en un servidor d'aplicacions complet

OpenResty: convertir NGINX en un servidor d'aplicacions completTornem a publicar la transcripció de l'informe de la conferència HighLoad ++ 2016, que va tenir lloc a Skolkovo, prop de Moscou, del 7 al 8 de novembre de l'any passat. Vladimir Protasov explica com estendre la funcionalitat de NGINX amb OpenResty i Lua.

Hola a tots, em dic Vladimir Protasov, treballo a Parallels. Us parlaré una mica de mi. Em passo tres quartes parts de la meva vida escrivint codi. Em vaig convertir en un programador fins al nucli en el sentit literal: de vegades veig codi en els meus somnis. Una quarta part de la vida és desenvolupament industrial, escrivint codi que entra directament a la producció. Un codi que alguns de vosaltres feu servir però que no us n'adoneu.

Així que entens el dolent que va ser. Quan era una mica jove, vaig venir i em van donar aquestes bases de dades de dos terabytes. És una gran càrrega per a tothom aquí ara. Vaig anar a conferències i vaig preguntar: “Nois, digueu-me, teniu big data, està tot genial? Quantes bases hi tens? Em van respondre: "Tenim 100 gigabytes!" Vaig dir: "Genial, 100 gigabytes!" I estava pensant per a mi mateix com mantenir acuradament la meva cara de pòquer. Penses que sí, els nois són genials, i després tornes a jugar amb aquestes bases de dades de diversos terabytes. I això és ser un júnior. Us imagineu quin cop és aquest?

Conec més de 20 llenguatges de programació. Això és una cosa que vaig haver de descobrir mentre treballava. Et donen codi en Erlang, C, C++, Lua, Python, Ruby, una altra cosa, i ho has de tallar tot. En general, ho havia de fer. No va ser possible calcular el nombre exacte, però cap al dia 20 es va perdre el nombre.

Com que tots els presents saben què és Parallels i què fem, no parlaré de com som i què fem. Només us diré que tenim 13 oficines a tot el món, més de 300 empleats, desenvolupament a Moscou, Tallinn i Malta. Si ho desitgeu, podeu agafar-lo i traslladar-vos a Malta si a l'hivern fa fred i necessiteu escalfar-vos l'esquena.

Concretament, el nostre departament escriu en Python 2. Estem en el negoci i no tenim temps per implementar tecnologies de moda, així que patim. Utilitzem Django perquè ho té de tot, i vam agafar allò que no era necessari i el vam llençar. També MySQL, Redis i NGINX. També tenim moltes altres coses interessants. Tenim MongoDB, tenim conills corrent, ho tenim de tot, però no és meu i no ho faig.

OpenResty

Vaig parlar de mi mateix. Anem a esbrinar de què parlaré avui:

  • Què és OpenResty i amb què es menja?
  • Per què reinventar una altra roda quan tenim Python, NodeJS, PHP, Go i altres coses interessants amb les quals tothom està content?
  • I alguns exemples de la vida. Vaig haver de retallar molt l'informe perquè em va costar 3,5 hores, així que hi haurà pocs exemples.

OpenResty és NGINX. Gràcies a ell, tenim un servidor web complet que està ben escrit i funciona ràpidament. Crec que la majoria de nosaltres utilitzem NGINX en producció. Tots sabeu que és ràpid i genial. Hi van fer una E/S síncrona fantàstica, de manera que no hem de fer cicles de res, tal com van fer-ho a Python. Gevent és genial, genial, però si escriviu codi C i alguna cosa va malament, amb Gevent us tornaràs boig depurant-lo. Vaig tenir l'experiència: vaig trigar dos dies sencers a esbrinar què va fallar allà. Si algú no hagués excavat durant diverses setmanes, hagués trobat el problema, hagués escrit a Internet i Google no l'hagués trobat, ens hauríem tornat completament bojos.

NGINX ja té la memòria cau i el contingut estàtic fet. No us cal que us preocupeu de com fer-ho humanament, per no frenar en algun lloc, per no perdre els descriptors en algun lloc. Nginx és molt còmode de desplegar, no cal que penseu què heu de prendre: WSGI, PHP-FPM, Gunicorn, Unicorn. S'ha instal·lat Nginx, donat als administradors, saben com treballar-hi. Nginx processa les sol·licituds de manera estructurada. En parlaré una mica més tard. En definitiva, té una fase en què acaba d'acceptar la sol·licitud, quan la va tramitar i quan va servir el contingut a l'usuari.

Nginx és genial, però hi ha un problema: no és prou flexible, fins i tot amb totes les característiques interessants que els nois han incorporat a la configuració, malgrat el que es pot configurar. Aquest poder no és suficient. És per això que els nois de Taobao, fa molt de temps, sembla que fa vuit anys, hi van incorporar Lua. Què dóna?

  • mida. És petit. LuaJIT ofereix uns 100-200 kilobytes de sobrecàrrega de memòria i una sobrecàrrega de rendiment mínima.
  • Accelerar. L'intèrpret LuaJIT s'acosta a C en moltes situacions, en algunes situacions perd a Java, en altres el supera. Durant algun temps es va considerar l'estat de l'art, el compilador JIT més fantàstic. Ara n'hi ha de més freds, però són molt pesats, per exemple, el mateix V8. Alguns intèrprets JS i Java HotSpot són més ràpids en alguns moments, però en alguns llocs encara perden.
  • Fàcil d'aprendre. Si teniu, per exemple, una base de codi Perl i no feu reserva, no trobareu programadors Perl. Com que no existeixen, se'ls van endur tots, i ensenyar-los és llarg i difícil. Si voleu programadors per a una altra cosa, potser també haureu de tornar-los a formar o trobar-los. En el cas de Lua, tot és senzill. Qualsevol jove pot aprendre Lua en tres dies. Vaig trigar unes dues hores a esbrinar-ho. Dues hores després ja estava escrivint codi en producció. Aproximadament una setmana després va anar directament a la producció i va marxar.

Com a resultat, es veu així:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Aquí hi ha molt. OpenResty ha recopilat un munt de mòduls, tant de luash com de motor. I ho teniu tot a punt: desplegat i funcionant.

Примеры

Ja n'hi ha prou amb la lletra, passem al codi. Aquí teniu un petit Hola món:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Què hi ha? Aquesta és una ubicació d'Engins. No ens preocupem, no escrivim el nostre propi encaminament, no n'agafem un de fet, ja el tenim a NGINX, portem una vida bona i mandrosa.

content_by_lua_block és un bloc que diu que estem publicant contingut mitjançant un script Lua. Prenem la variable Engins remote_addr i posar-lo string.format. És el mateix que sprintf, només en Lua, només correcte. I li donem al client.

Com a resultat, quedarà així:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Però tornem al món real. Ningú desplega Hello World a la producció. La nostra aplicació sol anar a la base de dades o a un altre lloc i la majoria de les vegades espera una resposta.

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Només s'asseu i espera. No és gaire bo. Quan arriben 100.000 usuaris, ens és molt difícil. Per tant, utilitzem una aplicació senzilla com a exemple. Buscarem imatges, per exemple, de gats. Però no només cercarem, ampliarem les paraules clau i, si l'usuari ha cercat "gatitos", trobarem gats, gats peluts, etc. Primer, hem d'obtenir les dades de la sol·licitud al backend. Es veu així:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Dues línies us permeten recollir els paràmetres GET, sense complicacions. A continuació, posem per cas, d'una base de dades amb un signe per a una paraula clau i una extensió, obtenim aquesta informació mitjançant una consulta SQL normal. És fàcil. Es veu així:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Connexió de la biblioteca resty.mysql, que ja tenim al kit. No necessitem instal·lar res, ja està tot a punt. Us indiquem com connectar i fer una consulta SQL:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Aquí fa una mica de por, però tot funciona. Aquí 10 és el límit. Traiem 10 entrades, som mandrosos, no volem mostrar-ne més. Em vaig oblidar del límit en SQL.

A continuació trobarem imatges per a totes les consultes. Recollim un munt de peticions i omplim una taula Lua anomenada reqs, i ho fem ngx.location.capture_multi.

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Totes aquestes sol·licituds s'envien paral·lelament i se'ns retornen les respostes. El temps de funcionament és igual al temps de resposta del més lent. Si tots disparem en 50 mil·lisegons i enviem un centenar de sol·licituds, rebrem una resposta en 50 mil·lisegons.

Com que som mandrosos i no volem escriure HTTP i gestió de la memòria cau, farem que NGINX ho faci tot per nosaltres. Com heu vist, hi havia una petició url/fetch, aquí està ell:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Ho fem senzill proxy_pass, us indiquem on guardar la memòria cau, com fer-ho i tot ens funciona.

Però això no és suficient, encara hem de donar les dades a l'usuari. La idea més senzilla és serialitzar tot en JSON, fàcilment, en dues línies. Donem Content-Type, donem JSON.

Però hi ha una dificultat: l'usuari no vol llegir JSON. Hem d'atreure desenvolupadors front-end. De vegades no volem fer això al principi. I els especialistes en SEO diran que si busquem imatges, no els importa. I si els donem contingut, diran que els nostres cercadors no indexen res.

Què fer al respecte? Per descomptat, donarem HTML a l'usuari. Generar a mà no és comme il faut, per tant volem utilitzar plantilles. Hi ha una biblioteca per a això lua-resty-template.

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Segurament heu vist les tres lletres espantoses OPM. OpenResty inclou el seu propi gestor de paquets, mitjançant el qual podeu instal·lar un munt de mòduls diferents, en particular, lua-resty-template. Aquest és un motor de plantilles senzill, similar a les plantilles de Django. Allà podeu escriure codi i realitzar la substitució de variables.

Com a resultat, tot es veurà com aquest:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Vam agafar les dades i vam renderitzar la plantilla, de nou en dues línies. L'usuari està content, va rebre gats. Com que vam ampliar la sol·licitud, també va rebre una foca per a gatets. Mai se sap, potser estava buscant exactament això, però no va poder formular la seva petició correctament.

Tot està bé, però estem en desenvolupament i encara no volem mostrar-ho als usuaris. Fem l'autorització. Per fer-ho, mirem com NGINX gestiona la sol·licitud en termes d'OpenResty:

  • Primera fase - access, quan acabava d'arribar l'usuari, i el vam mirar per capçaleres, per adreça IP i per altres dades. El podem tallar immediatament si no ens agrada. Això es pot utilitzar per a l'autorització, o si rebem moltes sol·licituds, podem tallar-les fàcilment en aquesta fase.
  • nova versió. Reescriurem algunes dades de la sol·licitud.
  • contingut. Entreguem el contingut a l'usuari.
  • filtre de capçaleres. Substituïm les capçaleres de resposta. Si fem servir proxy_pass, podem reescriure algunes capçaleres abans de donar-les a l'usuari.
  • filtre corporal. Podem canviar el cos.
  • log - registre. Podeu escriure registres a elasticsearch sense cap capa addicional.

La nostra autorització tindrà un aspecte semblant a això:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Això l'afegirem a aquest location, que hem descrit abans, i hi posem el codi següent:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Mirem si tenim un testimoni de galeta. Si no és així, demanem autorització. Els usuaris són astuts i poden endevinar que necessiten configurar un testimoni de galeta. Per tant, també ho posarem a Redis:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

El codi per treballar amb Redis és molt senzill i no és diferent dels altres idiomes. Al mateix temps, totes les entrades/sortides, aquí i allà, no estan bloquejant. Si escriviu codi síncron, funciona de manera asíncrona. Gairebé com gevent, però ben fet.

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Fem l'autorització per si mateix:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

Diem que hem de llegir el cos de la sol·licitud. Rebem arguments POST i comprovem que l'inici de sessió i la contrasenya són correctes. Si són incorrectes, us desafiem per obtenir l'autorització. I si és correcte, escriviu el testimoni a Redis:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

No us oblideu de configurar la galeta, això també es fa en dues línies:

OpenResty: convertir NGINX en un servidor d'aplicacions complet

L'exemple és senzill i especulatiu. Per descomptat, no farem un servei que mostri gats a la gent. Però qui ens coneix. Així que repassem què es pot fer en producció.

  • Backend minimalista. De vegades necessitem enviar només una mica de dades al backend: en algun lloc hem d'inserir una data, en algun lloc hem de mostrar una llista, dir quants usuaris hi ha ara al lloc, adjuntar un comptador o estadístiques. Una cosa tan petita. Algunes peces mínimes es poden fer molt fàcilment. Això farà que sigui ràpid, fàcil i fantàstic.
  • Preprocessament de dades. De vegades volem inserir publicitat a la nostra pàgina i rebem aquesta publicitat mitjançant sol·licituds d'API. Això és molt fàcil de fer aquí. No carreguem el nostre backend, que ja està assegut i treballant dur. Podeu recollir-lo i recollir-lo aquí. Podem combinar algun JS o, per contra, desacoblar-lo i preprocessar alguna cosa abans de donar-lo a l'usuari.
  • Façana per microservei. Aquest també és un cas molt bo, el vaig implementar. Abans d'això, vaig treballar a Tenzor, una empresa que s'ocupa d'informes electrònics i proporciona informes a aproximadament la meitat de les persones jurídiques del país. Vam crear un servei, s'hi van fer moltes coses utilitzant el mateix mecanisme: encaminament, autorització i més.
    OpenResty es pot utilitzar com a cola per als vostres microserveis, proporcionant un únic accés a tot i una única interfície. Com que els microserveis es poden escriure de tal manera que tingueu Node.js aquí, PHP aquí, Python aquí, alguna cosa d'Erlang aquí, entenem que no volem reescriure el mateix codi a tot arreu. Per tant, OpenResty es pot connectar a la part frontal.
  • Estadística i analítica. Normalment NGINX és a l'entrada i totes les sol·licituds passen per ella. És en aquest lloc on és molt convenient recollir. Podeu calcular alguna cosa immediatament i penjar-la en algun lloc, per exemple, Elasticsearch, Logstash, o simplement escriure-la al registre i enviar-la a algun lloc.
  • Sistemes multiusuari. Per exemple, els jocs en línia també són molt bons de fer. Avui a Ciutat del Cap, Alexander Gladysh parlarà sobre com crear ràpidament un prototip d'un joc multijugador amb OpenResty.
  • Filtrat de sol·licituds (WAF). Avui en dia està de moda fer tot tipus de tallafocs d'aplicacions web, hi ha molts serveis que els ofereixen. Amb OpenResty, podeu fer-vos un tallafoc d'aplicacions web que filtrarà les sol·licituds de manera senzilla i senzilla segons els vostres requisits. Si teniu Python, enteneu que PHP definitivament no s'injectarà en vosaltres, tret que, per descomptat, el genereu des de la consola. Ja sabeu que teniu MySQL i Python. Probablement, podrien intentar fer algun tipus de recorregut de directoris i injectar alguna cosa a la base de dades. Per tant, podeu filtrar les consultes estranyes de manera ràpida i econòmica al davant.
  • Comunitat. Com que OpenResty està construït a NGINX, té un avantatge: això comunitat NGINX. És molt gran i una part decent de les preguntes que tindreu al principi ja han estat resoltes per la comunitat NGINX.

    Desenvolupadors Lua. Ahir vaig parlar amb els nois que van venir a la jornada d'entrenament HighLoad++ i vaig sentir que només Tarantool estava escrit en Lua. Això no és cert, moltes coses estan escrites en Lua. Exemples: OpenResty, servidor Prosody XMPP, motor de joc Love2D, script Lua a Warcraft i en altres llocs. Hi ha molts desenvolupadors de Lua, tenen una comunitat gran i sensible. Totes les meves preguntes sobre Lua es van resoldre en poques hores. Quan escrius a la llista de correu, literalment en pocs minuts ja hi ha un munt de respostes, que descriuen què i com, què és què. És genial. Malauradament, una comunitat espiritual tan amable no és a tot arreu.
    Hi ha GitHub per a OpenResty, on podeu obrir un problema si es trenca alguna cosa. Hi ha una llista de correu a Google Groups, on podeu parlar de qüestions generals, hi ha una llista de correu en xinès; mai se sap, potser no parleu anglès, però sí que sabeu xinès.

Resultats de

  • Espero haver pogut transmetre que OpenResty és un marc molt convenient dissenyat per a la web.
  • Té una barrera d'entrada baixa, ja que el codi és semblant al que escrivim, el llenguatge és bastant senzill i minimalista.
  • Proporciona E/S asíncrona sense devolucions de trucada, no tindrem fideus com de vegades podem escriure a NodeJS.
  • Té un desplegament fàcil, ja que només necessitem NGINX amb el mòdul necessari i el nostre codi, i tot funciona de seguida.
  • Comunitat gran i sensible.

No vaig explicar amb detall com es fa l'encaminament, va resultar ser una història molt llarga.

Gràcies!

Reprodueix un vídeo

Vladimir Protasov - OpenResty: convertir NGINX en un servidor d'aplicacions complet

Font: www.habr.com

Afegeix comentari