新手的Flask+uwsgi+Nginx+Ubuntu部署過程

學(xué)習(xí) Flask,寫完一個(gè) Flask 應(yīng)用需要部署的時(shí)候,就想著折騰自己的服務(wù)器。根據(jù)搜索的教程照做,對于原理一知半解,磕磕碰碰,只要運(yùn)行起來了,謝天謝地然后不再折騰了,到下一次還需要部署時(shí),這樣的過程就會重復(fù)一次。不知道多少人的膝蓋中箭了呢?我也這樣干過,這么做確實(shí)很蠢,所以我決定寫一篇 Flask+uwsgi+Nginx+Ubuntu 的部署教程,解答一些我自己在這個(gè)過程中的疑問,從原理到方案,以一個(gè)小白的角度,總結(jié)一下部署、運(yùn)維這件事,應(yīng)該對初學(xué) Flask 需要部署的同學(xué)有些幫助。
more
環(huán)境簡介
Ubuntu
我使用的 Ubuntu 系統(tǒng)版本是 14.04,用過幾個(gè) Linux 發(fā)行版,現(xiàn)在挑選系統(tǒng)的第一選擇基本就是 Ubuntu 了,因?yàn)?Ubuntu 有商業(yè)公司 Canonical 做開發(fā)維護(hù);使用的人多,有龐大的社區(qū)支持;遇到問題容易解決。我折騰過很長時(shí)間的 Linux 系統(tǒng),我對新手的建議是,不要把時(shí)間浪費(fèi)在這上面,應(yīng)該以解決實(shí)際問題為導(dǎo)向,踏實(shí)點(diǎn)提高編程能力。裝系統(tǒng)、優(yōu)化系統(tǒng)、記各種酷炫的命令對于提高編程能力并沒有實(shí)際幫助。所以你問我資瓷不資瓷 Ubuntu,我當(dāng)然是資瓷的啦,用 Ubuntu 當(dāng)然也會遇到坑,但相比于其他系統(tǒng)會少一些,也會容易解決一點(diǎn)。事實(shí)上,Ubuntu 已經(jīng)成為了服務(wù)器的首選,AWS 上被選擇最多的 Linux 發(fā)行版就是 Ubuntu。Quora 用的 Linux 發(fā)行版也是 Ubuntu,創(chuàng)始人 Adam D'Angelo 在這個(gè)回答里解釋了原因。總的來說,沒有特別的理由的話,Ubuntu 理應(yīng)是首選,經(jīng)驗(yàn)多一些之后,如果對某個(gè)發(fā)行版感興趣,或者想要做一些特別的嘗試,跳出舒適區(qū),試試其他系統(tǒng)也無妨。
uWSGI
我們知道 Flask 中自帶了 web server,通過 Werkzeug,我們可以搭建 WSGI 服務(wù),運(yùn)行我們的網(wǎng)站,但 Flask 是 Web 框架,并不是 Web 服務(wù)器,盡管 Werkzeug 很強(qiáng)大,但只能用于開發(fā),不能用于生產(chǎn),對于 Web 服務(wù)器,我們有更專業(yè)的選擇,那就是 uWSGI, uWSGI 是一個(gè)全站式的托管服務(wù),它實(shí)現(xiàn)了應(yīng)用服務(wù)器(支持多種編程語言)、代理、進(jìn)程管理器、監(jiān)視器。取名為 uWSGI 是因?yàn)樗钤鐚?shí)現(xiàn)的是 Python 語言的 WSGI。
uWSGI 包括四個(gè)部分:
? uwsgi協(xié)議
? web server 內(nèi)置支持協(xié)議模塊
? application 服務(wù)器協(xié)議支持模塊
? 進(jìn)程控制程序
uWSGI 是 C 語言寫的,性能比較高。

WSGI, uWSGI, uwsgi 的區(qū)別
當(dāng)我們部署完一個(gè)應(yīng)用程序,瀏覽網(wǎng)頁時(shí)具體的過程是怎樣的呢?首先我們得有一個(gè) Web 服務(wù)器來處理 HTTP 協(xié)議的內(nèi)容,Web 服務(wù)器獲得客戶端的請求,交給應(yīng)用程序,應(yīng)用程序處理完,返回給 Web 服務(wù)器,這時(shí) Web 服務(wù)器再返回給客戶端。Web 服務(wù)器與應(yīng)用程序之間顯然要進(jìn)行交互,這時(shí)就出現(xiàn)了很多 Web 服務(wù)器與應(yīng)用程序之間交互的規(guī)范,最早出現(xiàn)的是 CGI,后來又出現(xiàn)了改進(jìn) CGI 性能的FasgCGI,Java 專用的 Servlet 規(guī)范,Python 專用的 WSGI 規(guī)范等等。有了統(tǒng)一標(biāo)準(zhǔn),程序的可移植性就大大提高了。這里我們只介紹 WSGI。
WSGI 全稱是 Web Server Gateway Interface,也就是 Web 服務(wù)器網(wǎng)關(guān)接口,它是 Python 語言定義出來的 Web 服務(wù)器和 Web 應(yīng)用程序之間的簡單而通用的接口,基于現(xiàn)存的 CGI 標(biāo)準(zhǔn)設(shè)計(jì),后來在很多其他語言中也出現(xiàn)了類似的接口。 總的來說,WSGI 可以分為服務(wù)器和應(yīng)用程序兩個(gè)部分,實(shí)際上可以將 WSGI 理解為服務(wù)器與應(yīng)用程序之間的一座橋,橋的一邊是服務(wù)器,另一邊是應(yīng)用程序。
按照 web 組件分類,WSGI 內(nèi)部可以分為三類,web 應(yīng)用程序,web 服務(wù)器,web 中間件。應(yīng)用程序端的部分通過Python 語言的各種 Web 框架實(shí)現(xiàn),比如 Flask,Django這些,有了框架,開發(fā)者就不需要處理 WSGI,框架會幫忙解決這些,開發(fā)者只需處理 HTTP 請求和響應(yīng),web 服務(wù)器的部分就要復(fù)雜一點(diǎn),可以通過 uWSGI 實(shí)現(xiàn),也可以用最常見的 Web 服務(wù)器,比如 Apache、Nginx,但這些 Web 服務(wù)器沒有內(nèi)置 WSGI 的實(shí)現(xiàn),是通過擴(kuò)展完成的。如 Apache,通過擴(kuò)展模塊 mod_wsgi 來支持WSGI,Nginx可以通過代理的方式,將請求封裝好,交給應(yīng)用服務(wù)器,比如 uWSGI。uWSGI 可以完成 WSGI 的服務(wù)端,進(jìn)程管理以及對應(yīng)用的調(diào)用。WSGI 中間件的部分可以這樣理解:我們把 WSGI 看做橋,這個(gè)橋有兩個(gè)橋墩,一個(gè)是應(yīng)用程序端,另一個(gè)是服務(wù)器端,那么橋面就是 WSGI 中間件,中間件同時(shí)具備服務(wù)器、應(yīng)用程序端兩個(gè)角色,當(dāng)然也需要同時(shí)遵守 WSGI 服務(wù)器和 WSGI 應(yīng)用程序兩邊的限制和需要。更詳細(xì)的內(nèi)容可以看PEP-333 中間件的描述
Flask 依賴的 Werkzeug 就是一個(gè) WSGI 工具包,官方文檔的定義是 Werkzeug 是為 Python 設(shè)計(jì)的 HTTP和 WSGI 實(shí)用程序庫。我們需要注意的是,F(xiàn)lask 自帶的 Werkzeug 是用來開發(fā)的,并不能用于生產(chǎn)環(huán)境,F(xiàn)lask 是 Web 框架,而 Werkzeug 不是 Web框架,不是 Web 服務(wù)器,它只是一個(gè) WSGI 工具包,它在 Flask 的作用是作為 Web 框架的底層庫,它方便了我們的開發(fā)。
我們將 uwsgi 和 uWSGI 放在一起講解。uWSGI 是一個(gè) Web 服務(wù)器程序,WSGI,上面已經(jīng)談到,是一種協(xié)議,uwsgi 也是一種協(xié)議,uWSGI 實(shí)現(xiàn)了 uwsgi、WSGI、http 等協(xié)議。 uwsgi 的介紹可以看這里,uwsgi 是 uWSGI 使用的一個(gè)自有的協(xié)議,它用4個(gè)字節(jié)來定義傳輸數(shù)據(jù)類型描述。盡管都是協(xié)議,uwsgi 和 WSGI 并沒有聯(lián)系,我們需要區(qū)分這兩個(gè)詞。
Nginx
Nginx 是高效的 Web 服務(wù)器和反向代理服務(wù)器,可以用作負(fù)載均衡(當(dāng)有 n 個(gè)用戶訪問服務(wù)器時(shí),可以實(shí)現(xiàn)分流,分擔(dān)服務(wù)器的壓力),與 Apache 相比,Nginx 支持高并發(fā),可以支持百萬級的 TCP 連接,十萬級別的并發(fā)連接,部署簡單,內(nèi)存消耗少,成本低,但 Nginx 的模塊沒有 Apache 豐富。Nginx 支持 uWSGI 的 uwsgi 協(xié)議,因此我們可以將 Nginx 與 uWSGI 結(jié)合起來,Nginx 通過 uwsgi_pass 將動態(tài)內(nèi)容交給 uWSGI 處理。

uWSGI 和 Nginx 的關(guān)系
從上面的講解中,我們知道,uWSGI 可以起到 Web 服務(wù)器的作用,那么為什么有了 uWSGI 還需要 Nginx 呢?
最普遍的說法是 Nginx 對于處理靜態(tài)文件更有優(yōu)勢,性能更好。其實(shí)如果是小網(wǎng)站,沒有靜態(tài)文件需要處理,只用 uWSGI 也是可以的,但加上 Nginx 這一層,優(yōu)勢可以很具體:
1 對于運(yùn)維來說比較方便,如果服務(wù)器被某個(gè) IP 攻擊,在 Nginx 配置文件黑名單中添加這個(gè) IP 即可,如果只用 uWSGI,那么就需要在代碼中修改了。另一方面,Nginx 是身經(jīng)百戰(zhàn)的 Web 服務(wù)器了,在表現(xiàn)上 uWSGI 顯得更專業(yè),比如說 uWSGI 在早期版本里是不支持 https 的,可以說 Nginx 更安全。
2 Nginx 的特點(diǎn)是能夠做負(fù)載均衡和 HTTP 緩存,如果不止一臺服務(wù)器,Nginx 基本就是必選項(xiàng)了,通過 Nginx,將資源可以分配給不同的服務(wù)器節(jié)點(diǎn),只有一臺服務(wù)器,也能很好地提高性能,因?yàn)?Nginx 可以通過 headers 的Expires or E-Tag,gzip 壓縮等方式很好地處理靜態(tài)資源,畢竟是 C 語言寫的,調(diào)用的是 native 的函數(shù),針對 I/O做了優(yōu)化,對于動態(tài)資源來說,Nginx 還可以實(shí)現(xiàn)緩存的功能,配合 CDN 優(yōu)化(這是 uWSGI 做不到的)。Nginx 支持epoll/kqueue 等高效網(wǎng)絡(luò)庫,能夠很好地處理高并發(fā)短連接請求,性能比 uWSGI 不知道高到哪里去了。
3 如果服務(wù)器主機(jī)上運(yùn)行了PHP,Python 等語言寫的多個(gè)應(yīng)用,都需要監(jiān)聽80端口,這時(shí)候 Nginx 就是必選項(xiàng)了。因?yàn)槲覀冃枰粋€(gè)轉(zhuǎn)發(fā)的服務(wù)。
所以說,Nginx 基本也是必選項(xiàng)。
部署準(zhǔn)備工作
這里我假設(shè)我們拿到的是一臺全新的服務(wù)器。 一般來說,Linux 系統(tǒng)都會預(yù)裝 Python 的,但不一定裝了 easy_install 工具,我們可以通過 apt-get install python-setuptools 來安裝 easy_install,再通過 easy_install 安裝 pip。
搞定 Python 環(huán)境

$ sudo apt-get install python-setuptools
$ sudo easy_install pip

我們也可以直接裝 pip:

$ sudo apt-get install python-pip

這樣,我們就可以通過 pip 安裝 virtualenv,為 flask 項(xiàng)目構(gòu)建虛擬環(huán)境。
VirtualEnv
不同的項(xiàng)目可能會引用各種不同的依賴包,為了避免版本與和應(yīng)用之間的沖突而造成的“依賴地獄”
[Virtualenv | https://virtualenv.readthedocs.org/en/latest/ ] 就是我們python 項(xiàng)目的必須品了。VirtualEnv 可以為每個(gè)Python應(yīng)用創(chuàng)建獨(dú)立的開發(fā)環(huán)境,使他們互不影響,Virtualenv 能夠做到:
? 在沒有權(quán)限的情況下安裝新套件
? 不同應(yīng)用可以使用不同的套件版本
? 套件升級不影響其他應(yīng)用
安裝:

sudo pip install virtualenv

安裝VirtualEnv 后只需要在項(xiàng)目目錄內(nèi)運(yùn)行 virtualenv 目錄名 就可以建立一個(gè)虛擬環(huán)境文件夾,然后啟用 activate 指令即可啟用該python虛擬環(huán)境,具體操作如下:
假定我的項(xiàng)目目錄叫 /home/www/my_flask ,首先安裝虛擬環(huán)境 (我習(xí)慣使用的虛擬環(huán)境目錄叫 venv )

my_flask root$ virtualenv venv

>> New python executable in venv/bin/python
>> Installing setuptools, pip...done.

在項(xiàng)目目錄下就會建立一個(gè)新的 venv 目錄,里面就是運(yùn)行python 的基本環(huán)境的工具與指令,和包。 然后啟用該環(huán)境,使用當(dāng)前命令行狀態(tài)進(jìn)入虛擬環(huán)境,進(jìn)入虛擬環(huán)境后,一切安裝python的操作都會將包和引用裝在虛擬環(huán)境內(nèi),而不會影響到全局的python 環(huán)境。

my_flask root$ source venv/bin/activate (進(jìn)入虛擬環(huán)境)

(venv)my_flask root$

調(diào)用 activate 指令后命令符前就會出現(xiàn) (venv) 字樣。 可通過 deactivate 退出虛擬環(huán)境。
安裝 uWSGI
Flask 的實(shí)際生產(chǎn)運(yùn)行環(huán)境選擇并不多,比較成熟的是 [Gunicorn| http://gunicorn.org/ ] 和 [uWSGI| https://github.com/unbit/uwsgi ] ,聽說Gunicorn 的配置很簡單,但可惜我一直沒有配置成功過,
在安裝 uWSGI 前,需要解決 uWSGI 的依賴問題,因?yàn)?uWSGI 是一個(gè) C 語言寫的應(yīng)用,所以我們需要 C 編譯器,以及 python 開發(fā)相關(guān)組件:

$ sudo apt-get install build-essential python-dev(這是兩個(gè)包)

我現(xiàn)采用的是 uWSGI。接下來就安裝uWSGI吧。

(venv)my_flask root$ pip install uwsgi

到這,我們就安裝好了 uWSGI,

在虛擬環(huán)境下不需要使用 sudo ,因?yàn)関irtualenv 是沒有權(quán)限要求的。
這個(gè)安裝很迅速,基本是秒成。安裝完成后我們可以先放下 uWSGI 不表,在后面再回過來配置他,因?yàn)槲覀兪紫纫獙㈥P(guān)鍵的 Flask環(huán)境和我們的項(xiàng)目文件傳到服務(wù)器目錄內(nèi)。
安裝 Flask

(venv)my_flask root$ pip install flask

可能由于服務(wù)器原因 一直安裝失敗,請重新安裝,所需依賴包可以自動安裝,不用管它

安裝Nginx

$ sudo apt-get install nginx

啟動 nginx 的方法:

$ sudo /etc/init.d/nginx start

這時(shí)候在瀏覽器地址欄輸入服務(wù)器的 ip 地址,看到下面的頁面就表明 Nginx 已經(jīng)啟動了:

開干
首先,我們把應(yīng)用程序上傳到服務(wù)器中,我在用 git 管理項(xiàng)目,所以只需要 git clone 一下就可以了:
$ git clone http://url/of/you/git/repo
如果你需要從本地上傳項(xiàng)目文件,可以用 scp 命令,這里就不啰嗦用法了。總之我們將項(xiàng)目文件放到服務(wù)器,然后就可以用 virtualenv 管理 Python 環(huán)境:

$ virtualenv ENV
$ source ENV/bin/activate         # 激活虛擬環(huán)境
$ pip install -r requirement.txt  # 解決依賴問題
$ deactivate                             # 退出依賴環(huán)境

這里就用 Flask 的7行代碼做示例吧,我新建了一個(gè)文件夾,名為 helloflask,將下面的內(nèi)容:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=5001)

保存為hello.py,運(yùn)行試試,在瀏覽器輸入服務(wù)器本機(jī)地址(192.168.1.X),加端口號5001就可以看到結(jié)果。
好了,現(xiàn)在我們用 Nginx 來承擔(dān) Web 服務(wù)。
修改 Nginx 的默認(rèn)配置文件:
文本編輯器打開 /etc/nginx/sites-enabled/default 文件
有心的話,其實(shí)可以從 Nginx 默認(rèn)配置中了解一些配置參數(shù),當(dāng)然最靠譜的途徑還是看 Nginx 的文檔。這里只簡單嘗試 Nginx,下面給出一個(gè)簡單的配置:

server {                                                                       
listen 80;                   # 服務(wù)器監(jiān)聽端口                                                 
server_name 110.110.110.110; # 這里寫你的域名或者公網(wǎng)IP                                                    
charset      utf-8;          # 編碼                                                  
client_max_body_size 75M;    # 之前寫的關(guān)于GET和POST的區(qū)別,這里應(yīng)該是原因之一吧                                                   

location / {                                                                   
    include uwsgi_params;         # 導(dǎo)入uwsgi配置                                            
    uwsgi_pass 127.0.0.1:8000;    # 轉(zhuǎn)發(fā)端口,需要和uwsgi配置當(dāng)中的監(jiān)聽端口一致                                             
    uwsgi_param UWSGI_PYTHON /home/自己創(chuàng)建的目錄/venv;       # Python解釋器所在的路徑(這里為虛擬環(huán)境)      
    uwsgi_param UWSGI_CHDIR /home/自己創(chuàng)建的目錄;             # 項(xiàng)目根目錄     
    uwsgi_param UWSGI_SCRIPT manage:app; (比如你測試用test.py文件,文件中app = Flask(__name__),那么這里就填  test:app
)            # 項(xiàng)目的主程序                           
      }                                                                              
}

修改完成后我們將上述內(nèi)容保存,稍作解釋:server_name 可以是域名,也可以寫 ip 地址,uwsgi_pass 是表明 Nginx 與 uwsgi 的交流方式,我這里用的是 sock 文件,當(dāng)然你也可以用指定端口號的形式,具體可以看這里。
重啟 Nginx:

sudo /etc/init.d/nginx restart

這時(shí)刷新一下之前打開的服務(wù)器公網(wǎng) ip(或綁定的域名),這時(shí)看到的就不是「Welcome to Nginx」,而是「502 Bad Way」,因?yàn)槲覀冞€沒有啟動 uWSGI,
編寫uwsgi配置文件
在項(xiàng)目文件根目錄新建配置文件uwsgi.ini(uwsgi支持多種配置文件格式, xml, ini, json等)
vim uwsgi.ini
寫入配置內(nèi)容如下:

[uwsgi]                                                                        
                                                                               
socket = 127.0.0.1:8000             # uwsgi的監(jiān)聽端口                                              
                                                                               
plugins = python                    # 這行一定要加上,不然請求時(shí)會出現(xiàn)-- unavailable modifier requested: 0 --錯(cuò)誤提示                                                   
                                                                               
chdir = /home/chihu                # 項(xiàng)目根目錄                                           
                                                                               
wsgi-file = manage.py               # flask程序的啟動文件                                           
                                                                     
callable = app                      # 程序變量名         

輸入:wq保存配置文件,可以通過uwsgi uwsgi.ini來啟動uwsgi。

稍稍解釋一下,socket 指定的是與 nginx 進(jìn)行通信的端口文件。
上面的內(nèi)容都是可以通過 uwsgi 命令的參數(shù)指定的,在命令行中敲入一行命令就可以了,為了「可持續(xù)發(fā)展」,當(dāng)然是用文件保存下來比較好。
通過 uwsgi 命令,--ini 參數(shù):

$ uwsgi --ini ini的文件名.ini &

指定配置文件,后臺運(yùn)行 uwsgi, 這時(shí)再刷新一下之前打開的頁面,就可以看到應(yīng)用正常運(yùn)行了。
我嘗試了在一臺服務(wù)器上運(yùn)行多個(gè)應(yīng)用,其實(shí)只需要改一下文件名,分別處理 uWSGI 和 Nginx 的配置文件即可(Nginx 的配置,可以寫在同一個(gè)文件中,寫兩個(gè) server 就行了)
常用命令
nginx 常用命令
啟動命令:

$ sudo nginx

$ sudo /usr/sbin/nginx

停止 nginx

$ sudo nginx -s stop

平滑啟動 nginx

sudo nginx -s reload

所謂平滑啟動就是在不停止 nginx 的情況下,重啟 nginx,重新加載配置文件,用新的工作進(jìn)程代替舊的工作進(jìn)程。
STEP 4: 進(jìn)程監(jiān)控
原本打算用uwsgi emperor的方式運(yùn)行uwsgi即讓uwsgi成為守護(hù)進(jìn)程(daemon),但是折騰了一天還是沒解決問題,遂換supervisor。(折騰uwsgi emperor到后面發(fā)現(xiàn)問題是,當(dāng)單獨(dú)使用uwsgi的時(shí)候一切正常,但一使用uwsgi emperor就會出現(xiàn)os.environ.get()獲取不到環(huán)境變量的問題,但環(huán)境變量明明可以通過env看到,直接在Python終端上執(zhí)行os.environ.get()也可以獲取到.....等有時(shí)間再回過頭了折騰。)
單獨(dú)一個(gè)uwsgi程序運(yùn)行短時(shí)間可能沒問題,但是網(wǎng)絡(luò)狀況瞬息萬變,萬一uwsgi進(jìn)程掛了網(wǎng)站也就訪問不了了.....為了防止出現(xiàn)意外情況,還需要一個(gè)監(jiān)控程序來監(jiān)控uwsgi的狀況,這里該supervisor出場了。具體什么是supervisor可以Google之。

  1. 首先安裝supervisor
sudo apt-get install supervisor
  1. 生成默認(rèn)配置文件
echo_supervisord_config > supervisord.conf
  1. 加入監(jiān)控程序的配置
[program:project_name]          # project_name這里寫上你的項(xiàng)目名稱,如我的為[project:chihu]
command = uwsgi --ini /home/chihu/uwsgi.ini  # 跟手動啟動的命令一樣
stopsignal=QUIT
autostart=true
autorestart=true
stdout_logfile=/var/log/uwsgi/supervisor_chihu.log      # 運(yùn)行日志
stderr_logfile=/var/log/uwsgi/supervisor_chihu_err.log  # 錯(cuò)誤日志
  1. 啟動supervisord
supervisorctl reload
  1. 檢查uwsgi進(jìn)程是否正常運(yùn)行
ps aux|grep uwsgi

如果一切正常,此時(shí)應(yīng)該可以看到uwsgi進(jìn)程
嘗試kill掉uwsgi進(jìn)程看supervisor會不會重新啟動一個(gè)新的uwsgi進(jìn)程

sudo killall uwsgi

若再次通過ps aux|grep uwsgi查看發(fā)現(xiàn)有新的uwsgi進(jìn)程在運(yùn)行,那差不多可以祝你成功了, God bless you。
ERROR
supervisorctl reload
提示錯(cuò)誤
error: <class 'socket.error'>, [Errno 2] No such file or directory: file: /usr/lib/python2.7/socket.py line: 224
issue
只需手動啟動supervisord即可:

sudo supervisord -c configfile.conf

? 這里涉及到一個(gè)啟動程序的用戶的問題,好幾次莫名不能通過os.environ.get()到系統(tǒng)中的環(huán)境變量,導(dǎo)致程序出錯(cuò)。一步一步排查猜測是因?yàn)閱映绦虻挠脩舨黄ヅ涞膯栴},遂將啟動程序的用戶從root改為普通的登陸用戶,問題解決,但這里還有疑問,因?yàn)榄h(huán)境變量是設(shè)置在/et/environment當(dāng)中的,按理這里設(shè)置的應(yīng)該是全局都可以訪問的環(huán)境變量,但是當(dāng)用root用戶啟動程序時(shí)就不能訪問到環(huán)境變量,為了這個(gè)問題折騰了好幾天,總算解決了,但是當(dāng)中的疑惑還是需要好好思考探索。
后記:
? 折騰了兩天終于搞定,有時(shí)候教程看著簡單,你的配置也和教程一樣,但就是由于各種錯(cuò)誤無法運(yùn)行,雖然說計(jì)算機(jī)非0即1,是我們?nèi)祟愖钪覍?shí)可靠的伙伴,但是有時(shí)候就差那么一點(diǎn)點(diǎn),有可能是軟件環(huán)境不對亦或是我們電腦的打開方式不對...總之,就是要有那么個(gè)折騰的過程,所謂吃一塹長一智,不折騰折騰估計(jì)過后就忘了怎么回事了,還是要勤動手不放棄,雖然被一個(gè)uwsgi emperor折騰得快要懷疑人生了,但我還是堅(jiān)定不移地...改道supervisor了 :)
? ---
初次寫教程,文中可能有疏漏或?qū)懙貌粔蚯‘?dāng)?shù)牡胤剑€請各位看官多多包涵,歡迎指正和交流。如果部署的過程中有問題也歡迎留言,雖然不能保證可以解決。
-EOF-
參考:
Nginx+uwsgi+supervisor在Ubuntu上部署flask應(yīng)用
http://www.cnblogs.com/dspace/archive/2016/07/06/5647587.html #

阿里云部署 Flask + WSGI + Nginx 詳解
http://www.cnblogs.com/Ray-liang/p/4173923.html

寫給新手看的Flask+uwsgi+Nginx+Ubuntu部署教程
http://www.cnblogs.com/knarfeh/p/5616515.html

https://segmentfault.com/a/1190000004294634 # uwsgi及Nginx配置
http://vladikk.com/2013/09/12/serving-flask-with-nginx-on-ubuntu/#comment-2401229330 # uwsgi emperor
http://letgoof.me/2013/deploy-django-project-with-uwsgi-nginx-and-supervisor/ # supervisor配置
http://liyangliang.me/posts/2015/06/using-supervisor/ # supervisor & supervisord
1 Why do I need nginx when I have uWSGI
2 Web開發(fā)技術(shù)發(fā)展歷史
3 uWSGI 文檔
4 Web Server Gateway Interface
5 PEP-3333
6 digitalocean tutorials
7 CGI wiki
8 啄木鳥社區(qū) wsgi 介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容