Nginx、Gunicorn在伺服器中分別起什麼作用?

剛開始學習Python web,在部署到伺服器的時候接觸了Nginx、Gunicorn等,不理解它們分別起什麼作用。
我用Gunicorn直接部署也能夠做到外網訪問,那麼在Gunicorn上再套一層Nginx是為了什麼呢?
查閱了知乎上一部分相關問題,也沒有得到答案。
題意可能描述不清,麻煩各位解答疑惑:)


嗯,怎麼說呢,大部分人在gunicorn前面部署一層nginx的時候也的確沒有想過為什麼,他們只是覺得這樣顯得他們比較專業,而且幻想著加了一層nginx反向代理之後性能會有提升,恕我直言,請你們帶上腦子,一個單純的串聯結構怎麼可能提升性能?請好好想一想這個問題好嗎?
在前面增加一層nginx的情況主要是:

  1. 負載均衡。tornado之類的框架只支持單核,所以多進程部署需要反向負載均衡。gunicorn本身就是多進程其實不需要
  2. 靜態文件支持,經過配置之後,nginx可以直接處理靜態文件請求而不用經過Python伺服器,Python伺服器也可以返回特殊的http頭將請求rewrite到靜態文件。我說的是經過配置之後,你配置了嗎?
  3. 抗並發壓力。雖然不能提升qps,但是多一層前端,的確可以吸收一些瞬時的並發請求,讓nginx先保持住連接,然後後端慢慢消化,但說實話這種情況下服務體驗已經很糟糕了。但的確比服務掛掉強一些。
  4. rewrite之類的其他功能。配置了才有,配了嗎?
  5. 怕gunicorn的http解析有bug。這個姑且算有點道理,不過加一層負載均衡不一定能解決問題。

主要來說加一層可以給你一些你很可能不會去配置的額外的功能,這樣多少會給運維人員一些安慰,反正也不會有什麼性能損耗,也就是說不太會有壞處,所以大家都假裝自己很懂地加了一層反向負載均衡。其實不見得就沒有壞處,比如說可能會獲取不到對端IP地址(變成127.0.0.1了),或者可能會被X-Forwarded-For欺騙。

不過另一個角度來說,如果你的業務早晚會上規模,早晚有一天會用上反向負載均衡,提前配一個也對,不過應該用兩台伺服器,配在不同伺服器上。內部服務的情況下如果壓力不太大,很多其實都是gunicorn裸跑的,Python不是PHP,不用非得加個前端。


如果
- 只有一個應用,不需要負載均衡
- 只提供api服務,沒有靜態文件
- 不需要額外的訪問控制等功能

這樣是不是就不需要nginx等反向代理?

答案是需要。

nginx可以緩衝請求和響應。如果讓Gunicorn直接提供服務,瀏覽器發起一個請求,鑒於瀏覽器和網路情況都是未知的,http請求的發起過程可能比較慢,而Gunicorn只能等待請求發起完成後,才去真正處理請求,處理完成後,等客戶端完全接收請求後,才繼續下一個。

nginx緩存客戶端發起的請求,直到收完整個請求,轉發給Gunicorn,等Gunicorn處理完成後,拿到響應,再發給客戶端,這個流程是nginx擅長處理,而Gunicorn不擅長處理的。

因此將Gunicorn置於nginx後面,可以有效提高Gunicorn的處理能力。


1.負載均衡,nginx佔用80埠,g可以佔用多個非80埠;
2.攔截靜態請求;
3.偽靜態化並緩存,減少動態請求數量;
4.依賴於nginx強大的功能和性能,可以做訪問控制,限速,限連接數等等;


不套Gunicorn 也可以做到外網訪問,那為什麼還要套呢?是一樣的道理。
Nginx 是專業的伺服器,性能更好,更專業,並發更高,可以做負載均衡,可以做靜態文件緩存,還可以限制 ip 訪問的頻率等等。
Gunicorn 一般用來管理多個進程,有進程掛了Gunicorn可以把它拉起來,防止伺服器長時間停止服務,還可以動態調整 worker 的數量,請求多的時候增加 worker 的數量,請求少的時候減少,這就是所謂的 pre-fork 模型,這貌似就是它的主要優點。(worker 貌似就是進程,不是很確定,因為我們在使用的過程中沒有發現進程數量有變化。。。)
也可以用 supervisor 來啟動 Gunicorn,這樣即使Gunicorn 的管理進程掛了也可以自動起來。


我來補充幾點,
1.nginx用作https卸載 gunicorn在0.16 之前是不支持https的
2. gunicorn不支持http1.1
3.有了反向代理的存在,可以使後端使用不同版本的server成為可能,可以做到灰度發布等。
3.1 進一步說 有了nginx的存在我們可以把不同的url匹配到不同的伺服器,後端你可以跑一個gunicorn也可以把http://api1.example.com轉發給gunicorn 吧http://api2.example.com轉發到另外一個server
他可能跑的是另外一種語言寫的。
3.2 再進一步說nginx完全可以作為一個入口 後方有多個主機,部署了同一套業務,但有的機器壞掉了,如果前邊有東西擋一下完全可以在負載列表中把他down掉然後換上一台新的主機,有了nginx做 負載均衡 器的存在,使gunicorn水平擴展成了可能,想想直接裸著的gunicorn想做成水平擴展要怎麼做?直接在dns配置多個A記錄嗎?
4.日誌,nginx輸出的標準日誌包含了常用的訪問信息,可以直接做簡單的訪問分析,而gunicorn的日誌還需要配置。


5.網上都這麼用我照著教程來的沒有了會不會出什麼問題~

我剛開始做python的時候就困惑於這個問題,現在有了一段時間的經驗,重新審視了一遍,有了一點理解。不對的地方還請和我撕逼。反正我臉皮厚~


我們的考慮主要是

0. 保留80埠

1. SSL支持

2. 靜態文件

所以前面還是套了一個Nginx

補充一下

3.負載均衡

4.靜態緩存


我覺得這就是一個,新輪子要不要上生產線的問題。

web伺服器評價就兩個指標: 高可用 + 高性能

負載均衡,靜態文件支持,訪問控制等等這些都是web伺服器所需要解決的問題,而並不代表他們解決的品質。

把網站比作一台車,各種web請求當做路面,nginx經過了多年打磨,被證明是最強的輪子,除非主機down了,不然他不會down。gunicorn可以把nginx解決的問題逐個解決一遍,成為新輪子,但是我們誰願意承擔爆胎的風險呢。

生產環境還是要用別人驗證過的可靠方案。


推薦閱讀:

Python 如何入門?
那麼,Python做爬蟲究竟比其他語言好在哪裡呢?
關於用python抓取知乎關注的人?
有沒有什麼東西是 Go 可以做但 Python 做不到的?

TAG:Web開發 | Python | Nginx |