de ce ar trebui să folosesc un proxy invers dacă nod.js este gata de producție?
anul a fost 2012. PHP și Ruby on Rails au domnit ca tehnologii Supreme de server pentru redarea aplicațiilor web. Dar, un nou concurent îndrăzneț a luat comunitatea de furtună — una care a reușit să se ocupe de conexiuni concurente 1m. Această tehnologie a fost nimeni altul decât Node.js și a crescut constant în popularitate de atunci.spre deosebire de majoritatea tehnologiilor concurente ale timpului, Node.js a venit cu un server web încorporat. Având acest server, dezvoltatorii ar putea ocoli o multitudine de fișiere de configurare, cum ar fiphp.ini
și o colecție ierarhică de.htaccess
fișiere. Având un server web încorporat, de asemenea, a oferit alte facilități, cum ar fi capacitatea de a procesa fișierele pe măsură ce erau încărcate și ușurința implementării WebSockets.
în fiecare zi nod.aplicațiile web bazate pe js gestionează fericit miliarde de Cereri. Cele mai multe dintre cele mai mari companii din lume sunt alimentate într-un fel de nod.js. Pentru a spune că nodul.js este gata de producție este cu siguranță o subevaluare. Cu toate acestea, există un sfat care a avut loc adevărat de la nod.începutul lui js: nu ar trebui să expuneți direct un nod.proces js pe web și ar trebui să-l ascundă în spatele unui proxy invers. Dar, înainte de a ne uita la motivele pentru care am dori să folosim un proxy invers, să ne uităm mai întâi la ceea ce este unul.
un proxy invers este practic un tip special de server web care primește cereri, le transmite către un alt server HTTP în altă parte, primește un răspuns și transmite răspunsul către solicitantul inițial.
un proxy invers nu trimite, de obicei, cererea exactă, deși. De obicei, se va modifica cererea într-un fel. De exemplu, dacă proxy-ul invers trăiește lawww.example.org:80
și va transmite cererea cătreex.example.org:8080
, probabil va rescrie antetul originalHost
pentru a se potrivi cu cel al țintei. De asemenea, poate modifica cererea în alte moduri, cum ar fi curățarea unei cereri malformate sau traducerea între protocoale.
odată ce proxy-ul invers primește un răspuns, acesta poate traduce acel răspuns într-un fel. Din nou, o abordare comună este de a modifica Host
antet pentru a se potrivi cererea inițială. Corpul cererilor poate fi schimbat, de asemenea. O modificare comună este de a efectua compresia gzip asupra răspunsului. O altă modificare obișnuită este activarea suportului HTTPS atunci când serviciul de bază vorbește doar HTTP.
proxy-urile inverse pot, de asemenea, să expedieze cererile primite către mai multe instanțe backend. Dacă un serviciu este expus laapi.example.org
, un proxy invers ar putea transmite cereri cătreapi1.internal.example.org
api2
etc.
există multe proxy-uri inverse diferite acolo. Două dintre cele mai populare sunt Nginx și HAProxy. Ambele instrumente sunt capabile să efectueze compresie gzip și să adauge suport HTTPS și se specializează și în alte domenii. Nginx este cea mai populară dintre cele două opțiuni și are și alte capabilități benefice, cum ar fi capacitatea de a servi fișiere statice dintr-un sistem de fișiere, așa că îl vom folosi ca exemplu în acest articol.
acum că știm ce este un proxy invers, putem acum să analizăm de ce am dori să folosim unul cu nod.js.
De ce ar trebui să folosesc un Proxy invers?
terminarea SSL este unul dintre cele mai populare motive pentru care se folosește un proxy invers. Schimbarea protocolului aplicației ones de la http
la https
necesită ceva mai multă muncă decât adăugarea unui s
. Nod.js în sine este capabil să efectueze criptarea și decriptarea necesare pentru https
și poate fi configurat pentru a citi fișierele de certificat necesare.
cu toate acestea, configurarea protocolului utilizat pentru a comunica cu aplicația noastră și gestionarea certificatelor SSL care expiră în permanență nu este cu adevărat ceva de care aplicația noastră trebuie să fie preocupată. Verificarea certificatelor într-o bază de cod nu ar fi doar obositoare, ci și un risc de securitate. Achiziționarea certificatelor dintr-o locație centrală la pornirea aplicației are, de asemenea, riscurile sale.din acest motiv ,este mai bine să efectuați terminarea SSL în afara aplicației, de obicei într-un proxy invers. Datorită tehnologiilor precum certbot
de Let ‘ s Encrypt, menținerea certificatelor cu Nginx este la fel de ușoară ca configurarea unei lucrări cron. O astfel de lucrare poate instala automat noi certificate și reconfigura dinamic procesul Nginx. Acesta este un proces mult mai puțin perturbator atunci, să zicem, repornirea fiecărui nod.instanță aplicație js.
de asemenea, permițând unui proxy invers să efectueze rezilierea SSL, aceasta înseamnă că numai codul scris de autorii proxy invers are acces la certificatul SSL privat. Cu toate acestea, dacă nodul dvs.aplicația js gestionează SSL, apoi fiecare modul terț utilizat de aplicația dvs. — chiar și module potențial rău intenționate — va avea acces la certificatul dvs. SSL privat.
compresia gzip
compresia gzip este o altă caracteristică pe care ar trebui să o descărcați din aplicație într-un proxy invers. politicile de compresie gzip sunt cel mai bine stabilite la nivel de organizație, în loc să fie nevoie să specificați și să configurați pentru fiecare aplicație.
cel mai bine este să folosiți o logică atunci când decideți ce să gzip. De exemplu, fișierele care sunt foarte mici, poate mai mici decât 1KB, probabil că nu merită comprimate, deoarece versiunea comprimată gzip poate fi uneori mai mare sau este posibil ca CPU-ul să decomprimeze fișierul client să nu merite. De asemenea, atunci când aveți de-a face cu date binare, în funcție de format, este posibil să nu beneficieze de compresie. gzip este, de asemenea, ceva care nu poate fi pur și simplu activat sau dezactivat, este nevoie de examinarea de intrare Accept-Encoding
antet pentru algoritmi de compresie compatibile.
Clustering
JavaScript este un limbaj cu un singur fir și, în consecință, un nod.js a fost în mod tradițional o platformă de server cu un singur fir (deși, suportul pentru firul de lucru experimental Disponibil în Node.js v10 își propune să schimbe acest lucru). Aceasta înseamnă să obțineți cât mai mult transfer de la un nod.aplicarea js posibil necesită rulează aproximativ același număr de instanțe ca există nuclee CPU.
nod.js vine cu un built-incluster
modul care poate face doar asta. Cererile HTTP primite vor fi făcute unui proces principal, apoi vor fi expediate lucrătorilor din cluster.
cu toate acestea, scalarea dinamică a lucrătorilor din cluster ar necesita un efort. Există, de asemenea, de obicei, adăugat deasupra capului în care rulează un nod suplimentar.procesul js ca proces principal de expediere. De asemenea, scalarea proceselor pe diferite mașini este ceva ce cluster
nu poate face.
Din aceste motive, uneori este mai bine să folosiți un proxy invers pentru a trimite cereri către nodul care rulează.procese js. Astfel de proxy-uri inverse pot fi configurate dinamic pentru a indica noile procese de aplicație pe măsură ce ajung. Într-adevăr, o aplicație ar trebui să fie doar preocupat de a face munca proprie, nu ar trebui să fie preocupat de gestionarea mai multor copii și expedierea cererilor.
Enterprise Routing
când aveți de-a face cu aplicații web masive, cum ar fi cele construite de întreprinderi cu mai multe Echipe, este foarte util să aveți un proxy invers pentru a determina unde să redirecționați cererile. De exemplu, cererile făcute la example.org/search/*
pot fi direcționate către aplicația de căutare internă, în timp ce alte cereri făcute la example.org/profile/*
pot fi expediate către aplicația de profil intern.
o astfel de scule permite alte caracteristici puternice, cum ar fi sesiuni lipicioase, implementări albastre/verzi, testare A / B etc. Am lucrat personal într-o bază de cod în care o astfel de logică a fost efectuată în cadrul aplicației și această abordare a făcut ca aplicația să fie destul de greu de întreținut.
beneficii de performanță
nod.js este foarte maleabil. Este capabil să servească active statice dintr-un sistem de fișiere, să efectueze compresie gzip cu răspunsuri HTTP, vine cu suport încorporat pentru HTTPS și multe alte caracteristici. Ea are chiar capacitatea de a rula mai multe instanțe ale unei aplicații și de a efectua propria cerere de expediere, prin intermediul cluster
modul.
și totuși, în cele din urmă este în interesul nostru să lăsăm un proxy invers să se ocupe de aceste operațiuni pentru noi, în loc să avem nodul nostru.aplicația js o face. Altele decât fiecare dintre motivele enumerate mai sus, un alt motiv pentru care doresc să facă aceste operațiuni în afara nod.js se datorează eficienței.
criptarea SSL și compresia gzip sunt două operații extrem de legate de CPU. Instrumentele dedicate proxy invers, cum ar fi Nginx și HAProxy, efectuează de obicei aceste operații mai repede decât Node.js. Având un server web ca Nginx citit conținut static de pe disc va fi mai rapid decât nod.js, de asemenea. Chiar și gruparea poate fi uneori mai eficientă, deoarece un proxy invers, cum ar fi Nginx, va folosi mai puțină memorie și procesor decât cel al unui nod suplimentar.procesul js.
dar, nu luați cuvântul nostru pentru asta. Să rulăm câteva repere!
următoarele teste de încărcare au fost efectuate folosindsiege
. Am rulat comanda cu o valoare de concurență de 10 (10 utilizatori simultani care fac o solicitare) și comanda va rula până la 20.000 de iterații (pentru 200.000 de solicitări globale).
pentru a verifica memoria rulăm comandapmap <pid> | grep total
de câteva ori pe durata de viață a benchmark-ului, apoi media rezultatelor. Atunci când rulează Nginx cu un singur fir lucrător acolo sfârșesc prin a fi două instanțe care rulează, unul fiind maestru și celălalt fiind lucrătorul. Apoi rezumăm cele două valori. Când rulați un nod.JS cluster de 2 vor exista 3 procese, unul fiind maestrul și celelalte două fiind lucrători. Coloana de memorie aprox din tabelul următor este o sumă totală a fiecărui Nginx și nod.procesul js pentru testul dat.
aici sunt rezultatele de referință:
în node-cluster
benchmark folosim 2 lucrători. Aceasta înseamnă că există 3 noduri.procesele JS rulează: 1 maestru și 2 lucrători. Înnginx-cluster-node
benchmark avem 2 nod.procesele JS rulează. Fiecare test Nginx are un singur maestru Nginx și un singur proces de lucrător Nginx. Reperele implică citirea unui fișier de pe disc și nici Nginx, nici nod.js au fost configurate pentru a cache fișierul în memorie.
folosind Nginx pentru a efectua terminarea SSL pentru nod.js are ca rezultat o creștere a debitului de ~16% (749rps la 865rps). Utilizarea Nginx pentru a efectua compresia gzip are ca rezultat o creștere a debitului de ~50% (5.047 rps la 7.590 rps). Utilizarea Nginx pentru a gestiona un grup de procese a dus la o penalizare de performanță de ~-1% (8.006 rps la 7.908 rps), probabil din cauza cheltuielilor generale de transmitere a unei cereri suplimentare pe dispozitivul de rețea loopback.
în esență, utilizarea memoriei unui singur nod.procesul js este de ~600MB, în timp ce utilizarea memoriei unui proces Nginx este de aproximativ ~50MB. Acestea pot fluctua puțin în funcție de caracteristicile utilizate, de exemplu, Node.js folosește un ~13MB suplimentar atunci când efectuează terminarea SSL, iar Nginx folosește un ~4MB suplimentar atunci când este utilizat ca verset proxy invers care servește conținut static din sistemul de fișiere. Un lucru interesant de remarcat este că Nginx folosește o cantitate consistentă de memorie de-a lungul vieții sale. Cu Toate Acestea, Nod.js fluctuează constant datorită naturii de colectare a gunoiului JavaScript.
iată versiunile software-ului utilizat în timpul efectuării acestui benchmark:
- Nginx:
1.14.2
- nod.js:
10.15.3
- asediu:
3.0.8
testele au fost efectuate pe o mașină cu 16 GB de memorie, un i7-7500U CPU 4x2.70GHz
și kernel-ul Linux 4.19.10
. Toate fișierele necesare necesare pentru a recrea valorile de referință de mai sus sunt disponibile aici:
IntrinsicLabs/nodejs-reverse-proxy-benchmarks.
Cod aplicație simplificată
repere sunt frumos și toate, dar, în opinia mea, cele mai mari beneficii ale descărcării de lucru de la un nod.aplicația js la un proxy invers este cea a simplității codului. Ajungem să reducem numărul de linii de cod de aplicație imperativ potențial buggy și să îl schimbăm pentru configurație declarativă. Un sentiment comun în rândul dezvoltatorilor este că sunt mai încrezători în codul scris de o echipă externă de ingineri — cum ar fi Nginx — decât în codul scris de ei înșiși.
în loc să instalați și să gestionați middleware-ul de compresie gzip și să îl mențineți actualizat pe diferite noduri.proiecte js putem configura în schimb într-o singură locație. În loc să expediem sau să descărcăm certificate SSL și fie să le achiziționăm din nou, fie să repornim procesele de aplicație, putem folosi în schimb instrumentele existente de gestionare a certificatelor. În loc să adăugăm condiționări la aplicația noastră pentru a verifica dacă un proces este un maestru sau lucrător, putem descărca acest lucru într-un alt instrument.
un proxy invers permite aplicației noastre să se concentreze pe logica de afaceri și să uite de protocoale și gestionarea proceselor.