這一年是2012年.PHP和Ruby on Rails做爲渲染Web應用程序的最高服務器端技術而備受矚目。可是,一個大膽的新競爭者掀起了一場風暴 - 一個可以處理1M併發鏈接的人。這項技術不過是Node.js,從那之後一直穩步增加。php
與當時大多數競爭技術不一樣,Node.js內置了一個Web服務器。擁有這個服務器意味着開發人員能夠繞過無數的配置文件,例如文件php.ini
的分層集合.htaccess
。擁有內置的Web服務器還提供了其餘便利,例如在上載文件時處理文件的能力以及實現WebSockets的簡易性。node
天天Node.js驅動的Web應用程序都會愉快地處理數十億個請求。世界上大多數最大的公司都以Node.js的某種方式供電。說Node.js是生產就緒的固然是輕描淡寫。可是,自Node.js誕生以來,有一條建議是正確的:不該該直接將Node.js進程暴露給Web,而應該隱藏在反向代理以後。可是,在咱們搞清楚爲何要使用反向代理以前,讓咱們首先看一下它是什麼。nginx
反向代理基本上是一種特殊類型的Web服務器,它接收請求,將它們轉發到其餘地方的另外一個HTTP服務器,接收回復,並將回覆轉發給原始請求者。git
可是,反向代理一般不會發送確切的請求。一般,它會以某種方式修改請求。例如,若是反向代理服務於www.example.org:80
,而且要將請求轉發給ex.example.org:8080
它,它可能會重寫原始Host
標頭以匹配目標標頭。它還能夠經過其餘方式修改請求,例如清除格式錯誤的請求或在協議之間進行轉換。github
一旦反向代理接收到響應,它就能夠以某種方式轉換該響應。一樣,常見的方法是修改Host
標頭以匹配原始請求。請求的主體也能夠更改。常見的修改是對響應執行gzip壓縮。另外一個常見的變化是在底層服務只支持HTTP時啓用HTTPS支持。算法
反向代理也能夠將傳入的請求分派給多個後端實例。若是服務是在暴露api.example.org
,反向代理能夠將請求轉發給api1.internal.example.org
,api2
等後端
那裏有許多不一樣的反向代理。其中兩個比較受歡迎的是Nginx和HAProxy。這兩個工具都可以執行gzip壓縮並添加HTTPS支持,而且它們也專一於其餘領域。Nginx是兩種選擇中比較流行的,而且還具備一些其餘有益的功能,例如從文件系統提供靜態文件的能力,所以咱們將在本文中使用它做爲示例。api
既然咱們知道反向代理是緩存
SSL終止是使用反向代理的最多見緣由之一。從改變那些應用程序的協議http
,以https
不是追加的多一點的工做s
。Node.js的自己安全
https
,而且能夠配置爲讀取所需的證書文件。
可是,配置用於與咱們的應用程序通訊的協議以及管理過時的SSL證書並非咱們的應用程序須要關注的問題。將證書檢入代碼庫不只繁瑣,並且還存在安全風險。在應用程序啓動時從中心位置獲取證書也存在風險。
所以,最好在應用程序以外執行SSL終止,一般在反向代理中執行。感謝像Let's Encrypt這樣certbot
的技術,使用Nginx維護證書就像設置一個cron做業同樣簡單。這樣的做業能夠自動安裝新證書並動態從新配置Nginx進程。這是一個破壞性較小的過程,而後從新啓動每一個Node.js應用程序實例。
此外,經過容許反向代理執行SSL終止,這意味着
gzip壓縮是另外一個應該從應用程序卸載到反向代理的功能。gzip壓縮策略是在組織級別最好設置的,而沒必要爲每一個應用程序指定和配置。
在決定gzip的內容時最好使用一些邏輯。例如,很是小,可能小於1kb的文件可能不值得壓縮,由於gzip壓縮版本有時可能更大,或者讓客戶端解壓縮文件的CPU開銷可能不值得。此外,在處理二進制數據時,根據格式,它可能沒法從壓縮中受益。gzip也是沒法簡單啓用或禁用的東西,它須要檢查傳入的Accept-Encoding
頭以得到兼容的壓縮算法。
JavaScript是一種單線程語言,所以,Node.js傳統上是一個單線程服務器平臺(可是,Node.js v10中目前實驗性的工做線程支持旨在改變這一點)。這意味着從Node.js應用程序得到儘量多的吞吐量須要運行與CPU核心大體相同數量的實例。
Node.js帶有內置cluster
模塊,能夠作到這一點。將向主進程發送傳入的HTTP請求,而後將其分派給集羣工做程序。
可是,動態擴展集羣工做人員須要付出一些努力。在調度主進程中運行額外的Node.js進程時,一般還會增長開銷。此外,跨不一樣計算機的擴展過程是cluster
沒法作到的。
出於這些緣由,有時最好使用反向代理來分派運行Node.js進程的請求。這些反向代理能夠動態配置爲在新應用程序到達時指向它們。實際上,應用程序應該只關注本身的工做,它不該該關心管理多個副本和分派請求。
在處理大型Web應用程序(例如由多團隊企業構建的應用程序)時,使用反向代理來肯定將請求轉發到何處很是有用。例如,example.org/search/*
能夠將發出的請求路由到內部搜索應用程序,同時example.org/profile/*
能夠將其餘請求分派到內部配置文件應用程序。
這樣的工具容許其餘強大的功能,如粘性會話,藍/綠部署,A / B測試等。我我的在代碼庫中工做,在應用程序中執行此類邏輯,這種方法使應用程序很難維護。
Node.js具備很強的可塑性。它可以從文件系統提供靜態資源,使用HTTP響應執行gzip壓縮,內置支持HTTPS以及許多其餘功能。它甚至可以經過模塊運行應用程序的多個實例並執行本身的請求調度cluster
。
然而,最終讓反向代理爲咱們處理這些操做符合咱們的最佳利益,而不是讓咱們的Node.js應用程序執行它。除了上面列出的每一個緣由以外,想要在Node.js以外進行這些操做的另外一個緣由是效率。
SSL加密和gzip壓縮是兩個高度CPU綁定的操做。專用的反向代理工具,如Nginx和HAProxy,一般比Node.js更快地執行這些操做。像Nginx這樣的Web服務器從磁盤讀取靜態內容也會比Node.js更快。甚至羣集有時也會更有效,由於像Nginx這樣的反向代理將使用比其餘Node.js進程更少的內存和CPU。
可是,不要相信咱們的話。咱們來作一些基準吧!
使用如下進行如下負載測試siege
。咱們使用併發值10(同時發出10個請求的用戶)運行命令,命令將運行直到進行20,000次迭代(對於200,000個整體請求)。
爲了檢查內存,咱們pmap <pid> | grep total
在基準測試的整個生命週期中運行命令幾回,而後平均結果。當使用單個工做線程運行Nginx時,最終會運行兩個實例,一個是主服務器,另外一個是工做服務器。而後咱們將這兩個值相加。當運行Node.js集羣爲2時,將有3個進程,一個是主進程,另外兩個是工做進程。下表中的近似內存列是給定測試的每一個Nginx和Node.js過程的總和。
如下是基準測試的結果:
在node-cluster
基準測試中,咱們使用2個worker。這意味着有3個Node.js進程在運行:1個master和2個worker。在nginx-cluster-node
基準測試中,咱們運行了2個Node.js進程。每一個Nginx測試都有一個Nginx主服務器和一個Nginx工做進程。基準測試涉及從磁盤讀取文件,Nginx和Node.js都沒有配置爲將文件緩存在內存中。
使用Nginx爲Node.js執行SSL終止會致使吞吐量增長約16%(749rps到865rps)。使用Nginx執行gzip壓縮會致使吞吐量增長約50%(5,047rps至7,590rps)。使用Nginx管理進程集羣致使性能損失約-1%(8,006rps到7,908rps),這多是因爲在環回網絡設備上傳遞額外請求的開銷。
基本上,單個Node.js進程的內存使用量約爲600MB,而Nginx進程的內存使用量約爲50MB。根據所使用的功能,這些可能會略微波動,例如,Node.js 在執行SSL終止時使用額外的~13MB,而當用做反向代理時,Nginx使用額外的~4MB來提供來自文件系統的靜態內容。值得注意的一件事是Nginx在其整個生命週期中使用了一致的內存量。可是,因爲JavaScript的垃圾收集性質,Node.js不斷波動。
如下是執行此基準測試時使用的軟件版本:
1.14.2
10.15.3
3.0.8
測試是在具備16GB內存,i7-7500U CPU 4x2.70GHz
Linux和Linux內核的機器上進行的4.19.10
。從新建立上述基準測試所需的全部必要文件都可在此處得到:
IntrinsicLabs / nodejs-reverse-proxy-benchmarkmarks。
基準測試很好,但在我看來,將工做從Node.js應用程序卸載到反向代理的最大好處是代碼簡單。咱們能夠減小潛在錯誤的命令式應用程序代碼的行數,並將其交換爲聲明性配置。開發人員廣泛認爲,他們對由外部工程師團隊(如Nginx)編寫的代碼比對本身編寫的代碼更有信心。咱們能夠在一個位置配置它,而不是安裝和管理gzip壓縮中間件並使其在各類Node.js項目中保持最新。咱們能夠改成使用現有的證書管理工具,而不是運送或下載SSL證書,從新獲取或從新啓動應用程序流程。咱們能夠將其卸載到另外一個工具,而不是將條件添加到咱們的應用程序以檢查進程是主進程仍是工做進程。反向代理容許咱們的應用程序專一於業務邏輯並忘記協議和流程管理。
儘管Node.js徹底可以在生產中運行,但使用具備生產HTTP Node.js應用程序的反向代理提供了無數的好處。SSL和gzip等操做變得更快。SSL證書的管理能夠變得更簡單。所需的應用程序代碼量也減小了。我強烈建議您在下一個生產Node.js應用程序時使用反向代理。
公衆號:銀河系1號
聯繫郵箱:public@space-explore.com
(未經贊成,請勿轉載)