waarom zou ik een Reverse Proxy if Node gebruiken.is js klaar voor de productie?
het was Het jaar 2012. PHP en Ruby on Rails regeerden als de hoogste server-side technologieën voor het renderen van webapplicaties. Maar, een gewaagde nieuwe mededinger nam de gemeenschap door storm-een die erin geslaagd om 1m gelijktijdige verbindingen te behandelen. Deze technologie was niemand minder dan Node.js en is gestaag toegenomen in populariteit sindsdien.
In tegenstelling tot de meeste concurrerende technologieën van die tijd, Node.js kwam met een ingebouwde webserver. Het hebben van deze server betekende dat ontwikkelaars een groot aantal configuratiebestanden konden omzeilen, zoals php.ini
en een hiërarchische verzameling van.htaccess
bestanden. Het hebben van een ingebouwde webserver bood ook andere gemakken, zoals de mogelijkheid om bestanden te verwerken terwijl ze werden geüpload en het gemak van het implementeren van WebSockets.
dagelijks knooppunt.js-powered web applicaties gelukkig omgaan met miljarden Verzoeken. De meeste van de grootste bedrijven in de wereld worden aangedreven op een of andere manier door Node.js. Om dat knooppunt te zeggen.js is klaar voor de productie is zeker een understatement. Echter, er is een stuk van advies dat waar heeft gehouden sinds Node.js ‘ s inception: men moet een knoop niet direct blootstellen.js proces naar het web en moet in plaats daarvan verbergen achter een reverse proxy. Maar voordat we kijken naar de redenen waarom we een omgekeerde proxy zouden willen gebruiken, laten we eerst kijken naar wat een is.
een reverse proxy is in principe een speciaal type webserver die verzoeken ontvangt, doorstuurt naar een andere HTTP-server ergens anders, een antwoord ontvangt en het antwoord doorstuurt naar de oorspronkelijke aanvrager.
een reverse proxy verstuurt meestal niet de exacte aanvraag. Meestal zal het verzoek op een bepaalde manier te wijzigen. Bijvoorbeeld, als de reverse proxy leeft op www.example.org:80
, en het verzoek doorstuurt naarex.example.org:8080
, zal het waarschijnlijk de originele Host
header herschrijven om overeen te komen met die van het doel. Het kan het verzoek ook op andere manieren wijzigen, zoals het opschonen van een misvormd verzoek of het vertalen tussen protocollen.
zodra de reverse proxy een antwoord ontvangt, kan het dat antwoord op de een of andere manier vertalen. Een veelgebruikte aanpak is om de Host
header aan te passen aan het oorspronkelijke verzoek. De inhoud van de verzoeken kan ook worden gewijzigd. Een veel voorkomende wijziging is het uitvoeren van GZIP compressie op de respons. Een andere veel voorkomende wijziging is om HTTPS-ondersteuning in te schakelen wanneer de onderliggende service alleen HTTP spreekt.
Reverse proxy ‘ s kunnen ook inkomende verzoeken verzenden naar meerdere backend-instanties. Als een service wordt weergegeven op api.example.org
, kan een reverse proxy Verzoeken doorsturen naar api1.internal.example.org
api2
, enz.
Er zijn veel verschillende reverse proxies. Twee van de meest populaire zijn Nginx en HAProxy. Beide tools zijn in staat om gzip compressie uit te voeren en HTTPS-ondersteuning toe te voegen, en ze zijn ook gespecialiseerd in andere gebieden. Nginx is de meest populaire van de twee keuzes, en heeft ook een aantal andere
nuttige mogelijkheden zoals de mogelijkheid om statische bestanden van een bestandssysteem te dienen, dus we zullen het gebruiken als een voorbeeld in dit artikel.
nu we weten wat een reverse proxy is, kunnen we nu onderzoeken waarom we er een met Node willen gebruiken.js.
waarom zou ik een Reverse Proxy gebruiken?
SSL-beëindiging is een van de meest populaire redenen waarom men een reverse proxy gebruikt. Het veranderen van het Protocol van ones applicatie van http
naar https
vergt iets meer werk dan het toevoegen van een s
. Knooppunt.js zelf is in staat om de benodigde encryptie en decryptie uit te voeren voor https
, en kan geconfigureerd worden om de benodigde certificaatbestanden te lezen.
echter, het configureren van het protocol dat gebruikt wordt om te communiceren met onze applicatie, en het beheren van steeds aflopende SSL certificaten, is niet echt iets waar onze applicatie zich zorgen over hoeft te maken. Het controleren van certificaten in een codebase zou niet alleen vervelend zijn, maar ook een veiligheidsrisico. Het verwerven van certificaten vanaf een centrale locatie bij het opstarten van de aanvraag heeft ook zijn risico ‘ s.
om deze reden is het beter om SSL-beëindiging buiten de toepassing uit te voeren, meestal binnen een reverse proxy. Dankzij technologieën zoals certbot
door Let ‘ s Encrypt, is het onderhouden van certificaten met Nginx net zo eenvoudig als het opzetten van een cron-taak. Zo ‘ n taak kan automatisch nieuwe certificaten installeren en dynamisch het Nginx-proces opnieuw configureren. Dit is een veel minder storend proces dan, laten we zeggen, het herstarten van elk knooppunt.js toepassing instantie.
door het toestaan van een reverse proxy om SSL-beëindiging uit te voeren, betekent dit ook dat alleen code geschreven door de reverse proxy auteurs toegang heeft tot uw privé SSL certificaat. Echter, als uw knooppunt.js applicatie is het omgaan met SSL, dan elke derde partij module gebruikt door uw toepassing — zelfs potentieel schadelijke modules — zal toegang hebben tot uw eigen SSL-certificaat.
gzip compressie
gzip compressie is een andere functie die u van de toepassing naar een reverse proxy zou moeten loaden. gzip compressie beleid is iets wat het beste ingesteld op een organisatie niveau, in plaats van te specificeren en configureren voor elke toepassing.
Het is het beste om wat logica te gebruiken bij het beslissen wat te gzip. Bijvoorbeeld, bestanden die erg klein zijn, misschien kleiner dan 1kb, zijn waarschijnlijk niet de moeite waard om te comprimeren als de gzip gecomprimeerde versie kan soms groter zijn, of de CPU overhead van het hebben van de client decomprimeren van het bestand is misschien niet de moeite waard. Ook, bij het omgaan met binaire gegevens, afhankelijk van het formaat kan het niet profiteren van compressie. gzip is ook iets dat niet eenvoudig kan worden ingeschakeld of uitgeschakeld, het vereist het onderzoeken van de inkomende Accept-Encoding
header voor compatibele compressie algoritmen.
Clustering
JavaScript is een single-threaded taal, en dienovereenkomstig, Node.js is van oudsher een single-threaded server platform (hoewel, de momenteel experimentele worker thread ondersteuning beschikbaar in Node.js v10 wil hier verandering in brengen). Dit betekent dat je zoveel mogelijk doorvoer van een knooppunt krijgt.js applicatie mogelijk vereist ongeveer hetzelfde aantal gevallen als er CPU cores.
Node.js wordt geleverd met een ingebouwde cluster
module die precies dat kan doen. Inkomende HTTP-verzoeken zullen worden gedaan om een masterproces vervolgens worden verzonden naar cluster werknemers.
het dynamisch schalen van clusterwerkers zou echter enige inspanning vergen. Er is ook meestal toegevoegd overhead in het uitvoeren van een extra knooppunt.js proces als de dispatching master proces. Ook is het schalen van processen over verschillende machines iets dat cluster
niet kan.
om deze redenen is het soms beter om een reverse proxy te gebruiken om verzoeken naar draaiende Node te verzenden.js processen. Dergelijke reverse proxies kunnen dynamisch worden geconfigureerd om te wijzen op nieuwe applicatieprocessen als ze aankomen. Echt, een applicatie moet gewoon bezig zijn met het doen van zijn eigen werk, het moet niet bezig zijn met het beheren van meerdere kopieën en het verzenden van verzoeken.
Enterprise Routing
bij het omgaan met massale webapplicaties, zoals die gebouwd door multi-team ondernemingen, is het erg handig om een reverse proxy te hebben om te bepalen waar verzoeken naar doorgestuurd moeten worden. Bijvoorbeeld, verzoeken aan example.org/search/*
kunnen worden doorgestuurd naar de interne zoektoepassing, terwijl andere verzoeken aan example.org/profile/*
kunnen worden verzonden naar de interne profieltoepassing.
dergelijke tooling maakt andere krachtige functies mogelijk, zoals sticky sessions, Blauw / Groen implementaties, A / B testen, enz. Ik heb persoonlijk gewerkt in een codebase waar een dergelijke logica werd uitgevoerd binnen de applicatie en deze aanpak maakte de applicatie heel moeilijk te onderhouden.
prestatievoordelen
knooppunt.js is zeer kneedbaar. Het is in staat om statische activa van een bestandssysteem te dienen, gzip-compressie uit te voeren met HTTP-reacties, wordt geleverd met ingebouwde ondersteuning voor HTTPS en vele andere functies. Het heeft zelfs de mogelijkheid om meerdere instanties van een toepassing uit te voeren en zijn eigen verzoek dispatching uit te voeren, door middel van de cluster
module.
en toch is het uiteindelijk in ons belang om een reverse proxy deze bewerkingen voor ons te laten afhandelen, in plaats van onze Node te hebben.js toepassing Doe het. Anders dan elk van de hierboven genoemde redenen, een andere reden om deze bewerkingen buiten knooppunt te doen.js is te wijten aan efficiëntie.
SSL-encryptie en gzip-compressie zijn twee zeer CPU-gebonden bewerkingen. Speciale reverse proxy tools, zoals Nginx en HAProxy, voeren deze bewerkingen meestal sneller uit dan Node.js. Het hebben van een webserver zoals Nginx lezen statische inhoud van de schijf gaat sneller dan Node.js ook. Zelfs clustering kan soms efficiënter zijn omdat een reverse proxy zoals Nginx minder geheugen en CPU zal gebruiken dan die van een extra knooppunt.js proces.
maar geloof ons niet op ons woord. Laten we wat ijkpunten bekijken!
de volgende belastingtest werd uitgevoerd met siege
. We voerden het commando uit met een concurrency waarde van 10 (10 gelijktijdige gebruikers die een verzoek indienen) en het commando zou draaien tot 20.000 iteraties werden gemaakt (voor 200.000 totale Verzoeken).
om het geheugen te controleren voeren we het commando pmap <pid> | grep total
een paar keer uit gedurende de levensduur van de benchmark en dan gemiddeld de resultaten. Bij het draaien van Nginx met een enkele worker thread zijn er uiteindelijk twee instanties die draaien, een is de master en de andere is de werknemer. Dan tellen we de twee waarden op. Bij het uitvoeren van een Node.js cluster van 2 Er zullen 3 processen zijn, een is de meester en de andere twee zijn arbeiders. De kolom approx geheugen in de volgende tabel is een totale som van elke Nginx en Node.js proces voor de gegeven test.
Hier zijn de resultaten van de benchmark:
In de node-cluster
benchmark gebruiken we 2 werknemers. Dit betekent dat er 3 knooppunt.js processen lopen: 1 master en 2 werknemers. In denginx-cluster-node
benchmark hebben we 2 Node.js processen draaien. Elke Nginx-test heeft een enkele Nginx-master en een enkel Nginx-werkproces. Benchmarks omvatten het lezen van een bestand van schijf, en noch Nginx noch Node.js werd geconfigureerd om het bestand in het geheugen te cachen.
Nginx gebruiken om SSL-beëindiging voor Node uit te voeren.js resulteert in een toename van de doorvoer van ~16% (749rps tot 865rps). Het gebruik van Nginx om gzip-compressie uit te voeren resulteert in een toename van de doorvoer van ~50% (5.047 rps tot 7.590 rps). Het gebruik van Nginx om een cluster van processen te beheren resulteerde in een prestatie boete van ~-1% (8.006 rps tot 7.908 rps), waarschijnlijk als gevolg van de overhead van het doorgeven van een extra verzoek over het loopback netwerk apparaat.
in wezen het geheugengebruik van een enkele Node.js-proces is ~600MB, terwijl het geheugengebruik van een Nginx-proces rond ~50MB is. Deze kunnen een beetje fluctueren, afhankelijk van welke functies worden gebruikt, bijvoorbeeld, knooppunt.js gebruikt een extra ~13MB bij het uitvoeren van SSL-beëindiging, en Nginx gebruikt een extra ~4MB wanneer gebruikt als een reverse proxy vers die statische inhoud van het bestandssysteem. Een interessant ding om op te merken is dat Nginx gebruikt een consistente hoeveelheid geheugen gedurende zijn levensduur. Echter, Node.js voortdurend fluctueert als gevolg van de vuilnis-verzamelen aard van JavaScript.
Hier zijn de versies van de software die gebruikt wordt tijdens het uitvoeren van deze benchmark:
- Nginx:
1.14.2
- Node.js:
10.15.3
- Siege:
3.0.8
de tests werden uitgevoerd op een machine met 16 GB geheugen, een i7-7500U CPU 4x2.70GHz
, en Linux kernel 4.19.10
. Alle bestanden die nodig zijn om bovenstaande benchmarks opnieuw te maken zijn hier beschikbaar:
IntrinsicLabs/nodejs-reverse-proxy-benchmarks.
vereenvoudigde toepassingscode
Benchmarks zijn aardig en zo, maar naar mijn mening de grootste voordelen van het ontlasten van werk van een knooppunt.js toepassing op een reverse proxy is die van code eenvoud. We krijgen om het aantal regels van potentieel-buggy imperatieve applicatie code te verminderen en te ruilen voor declaratieve configuratie. Een gemeenschappelijk gevoel onder ontwikkelaars is dat ze meer vertrouwen in code geschreven door een extern team van ingenieurs — zoals Nginx — dan in code geschreven door zichzelf.
in plaats van GZIP compressie middleware te installeren en te beheren en up-to-date te houden over verschillende knooppunten.js projecten we kunnen in plaats daarvan configureren op een enkele locatie. In plaats van SSL-certificaten te verzenden of te downloaden en ze opnieuw te verwerven of applicatieprocessen opnieuw op te starten, kunnen we in plaats daarvan gebruik maken van bestaande certificate management tools. In plaats van voorwaarden toe te voegen aan onze applicatie om te controleren of een proces een meester of werknemer is, kunnen we dit naar een andere tool offloaden.
met een reverse proxy kan onze applicatie zich richten op zakelijke logica en protocollen en procesbeheer vergeten.