標籤:

使用uwsgi部署Flask,不使用Unix套接字連接Nginx

如果你在Google或者百度或者某些技術社區上面搜索uwsgi + Flask,你會發現大量的文章,是教你如何使用uwsgi + flask + Nginx搭建網站。如下圖所示:

怪現狀

而且這些文章,全部都像是約定俗成一樣,一定會首先用命令行啟動uwsgi,測試uwsgi與Flask運行是否正常,然後寫uwsgi的配置文件。然後使用Unix 套接字溝通uwsgi與Nginx。所以uwsgi的配置文件裡面一定會寫成類似於下面這樣:

socket = /xxx/yyy/zzz.sock

Nginx的配置一定有類似於下面這一段:

location / {
include uwsgi_params;
uwsgi_pass unix:///xxx/yyy/zzz.sock;
}

他們為什麼要這樣寫?因為他們看的別的博客上就是這樣寫的!他們知其然,但是不知其所以然。

有什麼問題?

這種寫法本身沒有問題,甚至Flask的官方文檔裡面也是這樣寫的,如下圖所示:

但是他們這樣寫,有一個基本前提——就是Flask程序、uwsgi、Nginx三個東西運行在同一個伺服器上。如果用Docker,那麼這三個東西甚至需要運行到一個容器裡面。

如果是一個小網站,伺服器資源足夠,那麼這樣寫沒有問題,Unix套接字安全性高,速度也快。

那麼如果你同一個伺服器上有三個Docker容器,每一個容器都有一個不同的網站,是不是每個容器裡面都需要安裝一個Nginx?

對於大一些的網站,Nginx需要做負載均衡,如果把Nginx和網站放在同一台伺服器上,無論是Nginx拖垮了伺服器,還是網站拖垮了伺服器,都會導致很嚴重的問題。

能不能實現,一個伺服器上直接安裝Nginx,然後伺服器上的三個網站分別在三個Docker容器裡面,每個容器裡面只有Flask和uwsgi,沒有Nginx?

如果你的網站大一些,你在A伺服器安裝Nginx,在B、C、D、E、F伺服器上不安裝Nginx,只安裝uwsgi + Flask,又怎麼做?

所以進入我們今天的主題,安裝uwsgi + Flask(或者Django),但是不安裝Nginx(Deploy Flask with uwsgi but without Nginx)

不使用Unix套接字的uwsgi

Unix套接字,本質上是一個文件(Unix/Linux哲學:一切皆文件),Nginx和uwsgi通過這個文件來進行通信。所以需要Nginx與uwsgi放在同一個機器上。

但實際上,uwsgi本身就是一個伺服器,A伺服器上的Nginx與B伺服器上的uwsgi之間是可以通過http進行通信的。

要讓uwsgi使用http進行通信,我們可以修改uwsgi的配置文件xxx.ini:

[uwsgi]
module = wsgi:app
master = true
process = 5
threads = 100
gevent = 100
async = 100
http-socket = 0.0.0.0:5001
virtualenv = /Users/kingname/.local/share/virtualenvs/ActiveScoreApi-Ax_h-Y5w

其他參數的意義不是本文的重點,我們要關心的是http-socket = 0.0.0.0:5001。它的作用把網站部署在本機的5001埠,並允許外網通過http訪問。

寫了這個配置文件以後,通過以下命令來啟動uwsgi:

uwsgi --ini xxx.ini

然後你使用IP:5001就可以訪問你的網站了。此時,如果你有Nginx,那麼只需要在Nginx上設置反向代理,把80埠的請求代理到5001埠即可。

同理,把uwsgi和網站放在Docker鏡像裡面,容器開放5001埠。宿主機或者其他機器上的Nginx直接通過IP:埠 就可以訪問容器裡面的uwsgi,不再需要設置Unix套接字了。

另外,如果你閱讀過uwsgi的官方文檔,你還會發現,除了http-socket = 0.0.0.0:5001外,你也可以把它改成http = 0.0.0.0:5001。那麼這兩種寫法是否一樣呢?

在官方文檔裡面特別區分了它們的使用場景:

The http and http-socket options are entirely different beasts. The first one spawns an additional process forwarding requests to a series of workers (think about it as a form of shield, at the same level of apache or nginx), while the second one sets workers to natively speak the http protocol. TL/DR: if you plan to expose uWSGI directly to the public, use --http, if you want to proxy it behind a webserver speaking http with backends, use --http-socket.

簡言之,如果你直接把uwsgi作為伺服器,uwsgi啟動以後,直接就把IP:埠拿給別人訪問,那麼你就可以使用http;如果你的uwsgi前面還擋了一個Nginx,那麼你就使用http-socket


推薦閱讀:

搭建博客(4)部署在nginx
【實戰分享】又拍雲 OpenResty / Nginx 服務優化實踐
寫給前端看的Nginx系列文章
Varnish 原理及使用介紹
Nginx葵花寶典—草根站長Nginx運維百科全書

TAG:uwsgi | Nginx | Flask |