varför ska jag använda en omvänd Proxy om nod.js är produktionsklar?

Thomas Hunter II
Thomas Hunter II

följ
Mar 28, 2019 · 9 min läs

året var 2012. PHP och Ruby on Rails regerade som den högsta serversidan för rendering av webbapplikationer. Men, en djärv ny utmanare tog samhället med storm-en som lyckades hantera 1m samtidiga anslutningar. Denna teknik var ingen annan än nod.js och har stadigt ökat i popularitet sedan dess.

Till skillnad från de flesta konkurrerande tekniker av tiden, nod.js kom med en webbserver inbyggd. Att ha den här servern innebar att utvecklare kunde kringgå en myriad av konfigurationsfiler som php.ini och en hierarkisk samling av
.htaccess filer. Att ha en inbyggd webbserver gav också andra bekvämligheter, som möjligheten att bearbeta filer när de laddades upp och enkel implementering av WebSockets.

varje dag nod.js-drivna webbapplikationer hanterar gärna miljarder förfrågningar. De flesta av de största företagen i världen drivs på något sätt av Node.js. Att säga den noden.js är produktionsklar är verkligen en underdrift. Det finns dock ett råd som har varit sant sedan Node.js inception: man bör inte direkt exponera en nod.js process till webben och bör istället gömma den bakom en omvänd proxy. Men innan vi tittar på orsakerna till att vi vill använda en omvänd proxy, låt oss först titta på vad man är.

en omvänd proxy är i grunden en speciell typ av webbserver som tar emot förfrågningar, vidarebefordrar dem till en annan HTTP-server någon annanstans, får ett svar och vidarebefordrar svaret till den ursprungliga begäran.

en omvänd proxy skickar vanligtvis inte den exakta begäran. Vanligtvis kommer det att ändra begäran på något sätt. Om den omvända proxyn till exempel lever på www.example.org:80 och kommer att vidarebefordra begäran till
ex.example.org:8080, kommer den förmodligen att skriva om originalet Host för att matcha målet. Det kan också ändra begäran på andra sätt, till exempel att rensa upp en felaktig begäran eller översätta mellan protokoll.

när omvänd proxy får ett svar kan det sedan översätta det svaret på något sätt. Återigen är ett vanligt tillvägagångssätt att ändra rubrikenHost för att matcha den ursprungliga begäran. Kroppen av förfrågningarna kan också ändras. En vanlig modifiering är att utföra gzip-komprimering på svaret. En annan vanlig förändring är att aktivera HTTPS-stöd när den underliggande tjänsten bara talar HTTP.

omvända proxyservrar kan också skicka inkommande förfrågningar till flera backend-instanser. Om en tjänst exponeras vid api.example.org kan en omvänd proxy vidarebefordra förfrågningar till api1.internal.example.orgapi2, etc.

det finns många olika omvända proxies där ute. Två av de mer populära är Nginx och HAProxy. Båda dessa verktyg kan utföra gzip-komprimering och lägga till HTTPS-stöd, och de specialiserar sig också på andra områden. Nginx är den mer populära av de två valen, och har också några andra
fördelaktiga funktioner som möjligheten att betjäna statiska filer från ett filsystem, så vi använder det som ett exempel i hela den här artikeln.

Nu när vi vet vad en omvänd proxy är, kan vi nu undersöka varför vi skulle vilja använda en med nod.js.

varför ska jag använda en omvänd Proxy?

SSL-uppsägning är en av de mest populära anledningarna till att man använder en omvänd proxy. Att ändra protokollet för en applikation från http till https tar lite mer arbete än att lägga till ett s. Nod.js själv kan utföra nödvändig kryptering och dekryptering för https och kan konfigureras för att läsa nödvändiga certifikatfiler.att konfigurera protokollet som används för att kommunicera med vår applikation och hantera ständigt utgående SSL-certifikat är dock inte något som vår applikation behöver vara oroad över. Att kontrollera certifikat i en kodbas skulle inte bara vara tråkigt utan också en säkerhetsrisk. Att förvärva certifikat från en central plats vid applikationsstart har också sina risker.

av den anledningen är det bättre att utföra SSL-uppsägning utanför applikationen, vanligtvis inom en omvänd proxy. Tack vare tekniker som certbot av Let ’ s Encrypt är det lika enkelt att underhålla certifikat med Nginx som att skapa ett cron-jobb. Ett sådant jobb kan automatiskt installera nya certifikat och dynamiskt omkonfigurera nginx-processen. Detta är en mycket mindre störande process då, säg, starta om varje nod.js ansökan instans.

genom att tillåta en omvänd proxy att utföra SSL-uppsägning betyder det också att endast kod skriven av de omvända proxyförfattarna har tillgång till ditt privata SSL-certifikat. Men om din nod.js ansökan hanterar SSL, då varje enskild tredje part modul som används av din ansökan-även potentiellt skadliga moduler-kommer att ha tillgång till din privata SSL-certifikat.

gzip-komprimering

gzip-komprimering är en annan funktion som du bör ladda från programmet till en omvänd proxy. gzip-komprimeringspolicyer är något som bäst ställs in på organisationsnivå istället för att behöva ange och konfigurera för varje applikation.

det är bäst att använda lite logik när man bestämmer vad man ska gzip. Till exempel är filer som är mycket små, kanske mindre än 1 kB, förmodligen inte värda att komprimera eftersom gzip-komprimerad version ibland kan vara större, eller CPU-kostnaden för att klienten dekomprimerar filen kanske inte är värt det. Också, när det handlar om binära data, beroende på formatet det kanske inte dra nytta av komprimering. gzip är också något som inte helt enkelt kan aktiveras eller inaktiveras, det kräver att man undersöker inkommande Accept-Encoding rubrik för kompatibla komprimeringsalgoritmer.

Clustering

JavaScript är ett enkeltrådat språk och följaktligen nod.js har traditionellt varit en enkeltrådad serverplattform (men det för närvarande experimentella arbetstrådsstödet tillgängligt i Node.js v10 syftar till att ändra detta). Detta innebär att få så mycket genomströmning från en nod.js ansökan som möjligt kräver att köra ungefär samma antal instanser som det finns CPU-kärnor.

nod.js levereras med en inbyggdcluster modul som kan göra just det. Inkommande HTTP-förfrågningar kommer att göras till en huvudprocess och skickas sedan till klusterarbetare.

men dynamiskt skalande klusterarbetare skulle ta lite ansträngning. Det finns också vanligtvis lagt overhead i att köra en ytterligare nod.js process som avsändande huvudprocessen. Skalningsprocesser över olika maskiner är också något som cluster inte kan göra.

av dessa skäl är det ibland bättre att använda en omvänd proxy för att skicka förfrågningar till löpande nod.JS processer. Sådana omvända proxyer kan konfigureras dynamiskt för att peka på nya applikationsprocesser när de anländer. Egentligen borde en applikation bara vara upptagen med att göra sitt eget arbete, det borde inte vara oroat över att hantera flera kopior och skicka förfrågningar.

Enterprise Routing

När det handlar om massiva webbapplikationer, till exempel de som byggts av flera teamföretag, är det mycket användbart att ha en omvänd proxy för att bestämma var man ska vidarebefordra förfrågningar till. Till exempel kan förfrågningar till example.org/search/* dirigeras till det interna sökprogrammet medan andra förfrågningar till example.org/profile/* kan skickas till det interna profilprogrammet.

sådant verktyg möjliggör andra kraftfulla funktioner som klibbiga sessioner, blå/gröna distributioner, A/B-testning etc. Jag har personligen arbetat i en kodbas där sådan logik utfördes inom applikationen och detta tillvägagångssätt gjorde applikationen ganska svår att underhålla.

prestandafördelar

nod.js är mycket formbar. Det kan betjäna statiska tillgångar från ett filsystem, utföra gzip-komprimering med HTTP-svar, levereras med inbyggt stöd för HTTPS och många andra funktioner. Det har till och med förmågan att köra flera instanser av en applikation och utföra sin egen begäran, genom modulen cluster.

och ändå är det i slutändan i vårt bästa intresse att låta en omvänd proxy hantera dessa operationer för oss, istället för att ha vår nod.js ansökan gör det. Annat än var och en av de skäl som anges ovan, en annan anledning till att vilja göra dessa operationer utanför Node.js beror på effektivitet.

SSL-kryptering och gzip-komprimering är två mycket CPU-bundna operationer. Dedikerade omvända proxyverktyg, som Nginx och HAProxy, utför vanligtvis dessa operationer snabbare än Node.js. Att ha en webbserver som Nginx läser statiskt innehåll från disken kommer att bli snabbare än Node.js också. Även kluster kan ibland vara effektivare eftersom en omvänd proxy som Nginx kommer att använda mindre minne och CPU än för en ytterligare nod.js process.

men ta inte vårt ord för det. Låt oss köra några riktmärken!

följande belastningstestning utfördes med siege. Vi körde kommandot med ett samtidighetsvärde på 10 (10 samtidiga användare som gör en förfrågan) och kommandot skulle köras tills 20 000 iterationer gjordes (för 200 000 totala förfrågningar).

för att kontrollera minnet kör vi kommandot pmap <pid> | grep total några gånger under benchmarkens livstid och genomsnittliga resultaten. När man kör Nginx med en enda arbetartråd blir det två instanser som körs, en är mästaren och den andra är arbetaren. Vi summerar sedan de två värdena. När du kör en nod.js cluster of 2 Det kommer att finnas 3 processer, en är mästaren och de andra två är arbetare. Ca-minneskolumnen i följande tabell är en total summa av varje Nginx och Nod.js process för det givna testet.

här är resultaten av riktmärket:

benchmark resultat

inode-cluster benchmark vi använder 2 arbetare. Det betyder att det finns 3 nod.JS processer körs: 1 master och 2 arbetare. Inginx-cluster-node riktmärke har vi 2 nod.JS processer körs. Varje nginx-test har en enda nginx-mästare och en enda nginx-arbetsprocess. Riktmärken innebär att man läser en fil från disk, och varken Nginx eller Node.js konfigurerades för att cacha filen i minnet.

använda Nginx för att utföra SSL-uppsägning för nod.js resulterar i en genomströmningsökning på ~16% (749rps till 865rps). Användning av Nginx för att utföra gzip-komprimering resulterar i en genomströmningsökning på ~50% (5,047 rps till 7,590 rps). Att använda Nginx för att hantera ett kluster av processer resulterade i en prestandastraff på ~-1% (8 006 rps till 7 908 rps), förmodligen på grund av att man skickade en ytterligare begäran över loopback-nätverksenheten.

i huvudsak minnesanvändningen av en enda nod.js-processen är ~600 MB, medan minnesanvändningen av en nginx-process är cirka ~50 MB. Dessa kan fluktuera lite beroende på vilka funktioner som används, till exempel nod.js använder ytterligare ~13 MB när SSL-uppsägning utförs, och Nginx använder ytterligare ~4 MB när den används som en omvänd proxyvers som serverar statiskt innehåll från filsystemet. En intressant sak att notera är att Nginx använder en konsekvent mängd minne under hela sin livstid. Men Nod.js fluktuerar ständigt på grund av JavaScript: s skräpsamlande natur.

här är versionerna av programvaran som används när du utför detta riktmärke:

  • Nginx: 1.14.2
  • nod.js: 10.15.3
  • Siege: 3.0.8

Testerna utfördes på en maskin med 16 GB minne, ett i7-7500U CPU 4x2.70GHz och Linuxkärnan 4.19.10. Alla nödvändiga filer som krävs för att återskapa ovanstående riktmärken finns här:
IntrinsicLabs / nodejs-reverse-proxy-benchmarks.

förenklad Applikationskod

riktmärken är trevliga och alla, men enligt min mening är de största fördelarna med att avlasta arbete från en nod.js ansökan till en omvänd proxy är att kod enkelhet. Vi får minska antalet rader med potentiellt buggy imperativ applikationskod och byta ut den för deklarativ konfiguration. En vanlig känsla bland utvecklare är att de är mer säkra på kod skriven av ett externt team av ingenjörer — som Nginx — än i kod skriven av sig själva.

istället för att installera och hantera gzip komprimering middleware och hålla den uppdaterad över olika nod.js-projekt vi kan istället konfigurera det på en enda plats. Istället för att skicka eller ladda ner SSL-certifikat och antingen återköpa dem eller starta om applikationsprocesser kan vi istället använda befintliga certifikathanteringsverktyg. Istället för att lägga till villkor i vår ansökan för att kontrollera om en process är en mästare eller arbetare kan vi ladda ner detta till ett annat verktyg.

en omvänd proxy gör att vår applikation kan fokusera på affärslogik och glömma protokoll och processhantering.



Lämna ett svar

Din e-postadress kommer inte publiceras.