Gunicorn與uWSGI


Gunicorn與uWSGI

perfork

perfork是一種服務端編程模型, Nginx, Gunicorn, uWSGI都是這種模型的實現, 簡單的說perfok就是master進程啟動注冊一堆信號處理函數, 創建listen socket fd, fork出多個worker子進程, 子進程執行accept循環處理請求(這里簡化模型, 當然也可以用select, epoll多路復用), master進程只負責監控worker進程狀態, 通過pipeline通信來控制worker進程.

perfork模型使用master進程來監控worker進程狀態, 避免了我們使用supervisor來監控進程, 還支持多種信號來控制worker的數量, 使得CPU能充分得到利用, 多個worker進程監聽同一端口, 可以配置reuse_port參數在worker進程間負載均衡.

Gunicorn與uWSGI都是基於perfork模型的WSGI服務器, 下面我們就來聊聊他們的區別。

Gunicorn

Gunicorn是使用Python實現的WSGI服務器, 直接提供了http服務, 並且在woker上提供了多種選擇, gevent, eventlet這些都支持, 在多worker最大化里用CPU的同時, 還可以使用協程來提供並發支撐, 對於網絡IO密集的服務比較有利.

同時Gunicorn也很容易就改造成一個TCP的服務, 比如doge重寫worker類, 在針對長連接的服務時, 最好開啟reuse_port, 避免worker進程負載不均。

uWSGI

不同於Gunicorn, uWSGI是使用C寫的, 它的socket fd創建, worker進程的啟動都是使用C語言系統接口來實現的, 在worker進程處理循環中, 解析了http請求后, 使用python的C接口生成environ對象, 再把這個對象作為參數塞到暴露出來的WSGI application函數中調用. 而這一切都是在C程序中進行, 只是在處理請求的時候交給python虛擬機調用application. 完全使用C語言實現的好處是性能會好一些.

除了支持http協議, uWSGI還實現了uwsgi協議, 一般我們會在uWSGI服務器前面使用Nginx作為負載均衡, 如果使用http協議, 請求在轉發到uWSGI前已經在Nginx這里解析了一遍, 轉發到uWSGI又會重新解析一遍. uWSGI為了追求性能, 設計了uwsgi協議, 在Nginx解析完以后直接把解析好的結果通過uwsgi協議轉發到uWSGI服務器, uWSGI拿到請求按格式生成environ對象, 不需要重復解析請求. 如果用Nginx配合uWSGI, 最好使用uwsgi協議來轉發請求.

除了是一個WSGI服務器, uWSGI還是一個開發框架, 它提供了緩存, 隊列, rpc等等功能, 在github找找就會發現有人用它的緩存寫了一個Django cache backend, 用它的隊列實現異步任務這些東西, 但是用了這些東西技術棧也就跟uWSGI綁定在一起, 所以一般也只是把uWSGI當作WSGI服務器來用。

Nginx

使用多個進程監聽同一端口就繞不開驚群這個話題, fork子進程, 子進程共享listen socket fd, 多個子進程同時accept阻塞, 在請求到達時內核會喚醒所有accept的進程, 然而只有一個進程能accept成功, 其它進程accept失敗再次阻塞, 影響系統性能, 這就是驚群. Linux 2.6內核更新以后多個進程accept只有一個進程會被喚醒, 但是如果使用epoll還是會產生驚群現象.

Nginx為了解決epoll驚群問題, 使用進程間互斥鎖, 只有拿到鎖的進程才能把listen fd加入到epoll中, 在accept完成后再釋放鎖.

但是在高並發情況下, 獲取鎖的開銷也會影響性能, 一般會建議把鎖配置關掉. 直到Nginx 1.9.1更新支持了socket的SO_REUSEPORT選項, 驚群問題才算解決, listen socket fd不再是在master進程中創建, 而是每個worker進程創建一個通過SO_REUSEPORT 選項來復用端口, 內核會自行選擇一個fd來喚醒, 並且有負載均衡算法.

Gunicorn與uWSGI都支持reuse_port選項, 在使用時可以通過壓測來評估一下reuse_port是否能提升性能.

一般我們會在Gunicorn/uWSGI前面再加一層Nginx, 這樣做的原因有一下幾點:

  1. 做負載均衡
  2. 靜態文件服務器
  3. 更安全
  4. 扛並發






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM