抵不住朋友的誘惑,今天終于入手了一臺阿里云服務器,是Ubuntu 1.4 32位版本,最初考慮是用來嘗嘗鮮只是買了個最低配的,價格算起來與在國外買個空間的價格相當吧(可能一年才貴100多),但用起來感覺就很不錯,速度那是一個字:快。
自從倒戈向Linux世界后,對于一切大而全的開發框架與軟件都有一種不討喜的感覺,個人更喜歡于使用那些小而精,高性能高產生力的軟件和開發框架,So 我現在的第一語言是Python和Coffee,開發框架就當然是 AngularJS (前端) + Flask (后端) ,關于 AngularJS 與 Flask 不在本文的敘述范圍之內,本文解決的是 Flask 最后一公里的問題:Linux 部署。
我采用的部署方案是:
- Web 服務器采用 uwsgi host Flask
- 用 Supervisor 引用 uwsgi 作常規啟動服務
- 基于 Nginx 作反向代理
首先, 阿里云服務器可以通過 SSH 指令在本機的終端進行遠程連接
ssh root@云服務器地址
輸入密碼進入后所有的操作與本地終端完全一至。
安裝 Python 環境
接下來是python , Ubuntu 的默認環境已經預裝 python 2.7 所以只需要安裝 python 的 pip 安裝工具即可。pip 用于安裝一些基于python 應用的軟件工具,在下文中將會頻繁使用。
PIP
如果用python 而不懂 [pip|http://pypi.python.org/] 那最好就快點腦補吧, 指令如下:
sudo apt-get install pip
不同的項目可能會引用各種不同的依賴包,為了避免版本與和應用之間的沖突而造成的“依賴地獄”
[Virtualenv | https://virtualenv.readthedocs.org/en/latest/] 就是我們python 項目的必須品了。VirtualEnv 可以為每個Python應用創建獨立的開發環境,使他們互不影響,Virtualenv 能夠做到:
- 在沒有權限的情況下安裝新套件
- 不同應用可以使用不同的套件版本
- 套件升級不影響其他應用
安裝:
sudo pip install virtualenv
安裝VirtualEnv 后只需要在項目目錄內運行 virtualenv
目錄名 就可以建立一個虛擬環境文件夾,然后啟用 activate
指令即可啟用該python虛擬環境,具體操作如下:
假定我的項目目錄叫 /home/www/my_flask
,首先安裝虛擬環境 (我習慣使用的虛擬環境目錄叫 venv )
1
2
3
4
|
my_flask root$ virtualenv venv >> New python executable in venv /bin/python >> Installing setuptools, pip... done . |
在項目目錄下就會建立一個新的 venv 目錄,里面就是運行python 的基本環境的工具與指令,和包。 然后啟用該環境,使用當前命令行狀態進入虛擬環境,進入虛擬環境后,一切安裝python的操作都會將包和引用裝在虛擬環境內,而不會影響到全局的python 環境。
1
2
3
|
my_flask root$ source venv /bin/activate (venv)my_flask root$ |
調用 activate
指令后命令符前就會出現 (venv) 字樣。 可通過 deactivate 退出虛擬環境。
安裝 uWSGI
Flask 的實際生產運行環境選擇并不多,比較成熟的是 [Gunicorn|http://gunicorn.org/] 和 [uWSGI|https://github.com/unbit/uwsgi] ,聽說Gunicorn 的配置很簡單,但可惜我一直沒有配置成功過,我現采用的是 uWSGI。接下來就安裝uWSGI吧。
1
|
(venv)my_flask root$ pip install uwsgi |
在虛擬環境下不需要使用 sudo
,因為virtualenv 是沒有權限要求的。
這個安裝很迅速,基本是秒成。安裝完成后我們可以先放下 uWSGI 不表,在后面再回過來配置他,因為我們首先要將關鍵的 Flask環境和我們的項目文件傳到服務器目錄內。
安裝 Flask
我是用清單文件一次性安裝Flask和他的相關依賴的,這樣會更快。我的引用清單是這樣的:
requirements.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
Flask==0.10.1 Flask-Login==0.2.11 Flask-Mail==0.9.1 Flask-Moment==0.4.0 Flask-PageDown==0.1.5 Flask-SQLAlchemy==2.0 Flask-Script==2.0.5 Flask-WTF==0.10.2 Flask-Cache==0.13.1 Flask-Restless==0.15.0 Flask-Uploads==0.1.3 Jinja2==2.7.3 Mako==1.0.0 Markdown==2.5.1 MarkupSafe==0.23 SQLAlchemy==0.9.8 WTForms==2.0.1 Werkzeug==0.9.6 html5lib==1.0b3 itsdangerous==0.24 six==1.8.0 awesome-slugify==1.6 |
可以想像,如果一個一個裝非瘋了不可。
安裝清單文件:
1
|
(venv)my_flask root$ pip install -r requirements.txt |
在此還是重重地提一下:一定要注意在運行這個安裝之前啟用了python 虛擬環境,否則會直接安裝到全局去的!
項目文件
接下來就是上傳 Flask的項目文件,之前我在各大的“轉載專業戶”里找了好多的資料,在這一步中大多只是在上面加個標準的Flask運行文件,雖說做個范例可以但說實在的這很讓人迷惑,為什么?先看看代碼吧:
1
2
3
4
5
6
7
|
from flask import Flask app = Flask(__name__) @app .route( "/" ) def hello(): return "Hello World!" |
生產環境內,誰會用這樣的代碼呢,這只是Flask 的最簡入門范,我的Flask項目中 app 是被做在包內的,相信很多人都是這樣做的,在包外我們采用 Flask Script 寫一個 manage.py 文件 作為啟動文件,這更方便于支持各種的項目,包括可以安裝到 window下的 FastCGI 中。
那么我的 這個 manage.py 是這個樣子的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
#!/usr/bin/env python import os if os.path.exists( '.env' ): print ( 'Importing environment from .env...' ) for line in open ( '.env' ): var = line.strip().split( '=' ) if len (var) = = 2 : os.environ[var[ 0 ]] = var[ 1 ] from app import create_app from flask.ext.script import Manager, Shell # 通過配置創建 app app = create_app(os.getenv( 'FLASK_CONFIG' ) or 'default' ) manager = Manager(app) def make_shell_context(): return dict (app = app) manager.add_command( "shell" , Shell(make_context = make_shell_context)) @manager .command def deploy(): """Run deployment tasks.""" pass if __name__ = = '__main__' : manager.run() |
這樣做我地開發環境可以這樣運行 Flask:
1
|
python manage.py runserver |
更詳細的做法請參考 [Flask Script|http://flask-script.readthedocs.org/en/latest/] 擴展
好吧,我們可以用 支持SSH的FTP工具將Flask項目文件上傳到服務器上,下面是整個項目文件結構:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
www/ └── my_flask │ ├── logs │ └── venv //虛擬目錄 │ │ ├── bin │ │ │ ├── activate │ │ │ ├── easy_install │ │ │ ├── gunicorn │ │ │ ├── pip │ │ │ └── python │ │ ├── include │ │ │ └── python2.7 -> /usr/include/python2.7 │ │ ├── lib │ │ │ └── python2.7 │ │ ├── local │ │ │ ├── bin -> /home/shenye/shenyefuli/bin │ │ │ ├── include -> /home/shenye/shenyefuli/include │ │ │ └── lib -> /home/shenye/shenyefuli/lib │ └── app //Flask 程序目錄 │ │ └── __init__.py //這是程序包文件。這個目錄下還有其它的文件此處略過 │ ├── manage.py │ ├── requirements.txt |
配置 uwsgi
好了,項目的準備工作已經做完了,是時候回過頭去配置 uwsgi 了,它的具體指令可以去看它的官方文檔,我們在這里采用其中的一種指令方式:配置起動。我采用 .ini文件作為配置,在項目目錄下創建一個 confg.ini (具體見下文)寫好后可以這樣執行
1
|
(venv)my_flask root$ uwsgi config.ini |
我認為是最簡單的方式,也容易更改。好了重要部分來了,config.ini 是這樣寫的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
[uwsgi] # uwsgi 啟動時所使用的地址與端口 socket = 127.0.0.1:8001 # 指向網站目錄 chdir = /home/www/ # python 啟動程序文件 wsgi-file = manage.py # python 程序內用以啟動的 application 變量名 callable = app # 處理器數 processes = 4 # 線程數 threads = 2 #狀態檢測地址 stats = 127.0.0.1:9191 |
注意 : callable=app 這個 app 是 manage.py 程序文件內的一個變量,這個變量的類型是 Flask的 application 類 。
運行 uwsgi
```
(venv)my_flask root$ uwsgi config.ini
[uWSGI] getting INI configuration from config.ini
*** Starting uWSGI 2.0.8 (64bit) on [Fri Dec 19 14:34:11 2014]
// 此處略去那些無用的啟動信息
Stats server enabled on 127.0.0.1:9191 fd: 15 ***
```
OK, 此時已經正常啟動 uwsgi 并將 Flask 項目載入其中了,ctrl+c 關閉程序。但這只是命令啟動形式,要使其隨同服務器啟動并作為后臺服務運行才是運營環境的實際所需要。因此接下來我們需要安裝另一個工具來引導 uwsgi 。
安裝 Supervisor
[Supervisor|http://supervisord.org/configuration.html]可以同時啟動多個應用,最重要的是,當某個應用Crash的時候,他可以自動重啟該應用,保證可用性。
1
|
sudo apt-get install supervisor |
Supervisor 的全局的配置文件位置在:
1
|
/etc/supervisor/supervisor .conf |
正常情況下我們并不需要去對其作出任何的改動,只需要添加一個新的 *.conf 文件放在
1
|
/etc/supervisor/conf .d/ |
下就可以,那么我們就新建立一個用于啟動 my_flask 項目的 uwsgi 的 supervisor 配置 (命名為:my_flask_supervisor.conf):
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[program:my_flask] # 啟動命令入口 command=/home/www/my_flask/venv/bin/uwsgi /home/www/my_flask/config.ini # 命令程序所在目錄 directory=/home/www/my_flask #運行命令的用戶名 user=root autostart=true autorestart=true #日志地址 stdout_logfile=/home/www/my_flask/logs/uwsgi_supervisor.log |
啟動服務
1
|
sudo service supervisor start |
終止服務
1
|
sudo service supervisor stop |
安裝 Nginx
[Nginx|http://nginx.com/]是輕量級、性能強、占用資源少,能很好的處理高并發的反向代理軟件。
1
|
sudo apt-get install nginx |
配置 Nginx
Ubuntu 上配置 Nginx 也是很簡單,不要去改動默認的 nginx.conf 只需要將
1
|
/ext/nginx/sites-available/default |
文件替換掉就可以了。
新建一個 default 文件:
1
2
3
4
5
6
7
8
9
10
11
12
|
server { listen 80; server_name XXX.XXX.XXX; #公網地址 location / { include uwsgi_params; uwsgi_pass 127.0.0.1:8001; # 指向uwsgi 所應用的內部地址,所有請求將轉發給uwsgi 處理 uwsgi_param UWSGI_PYHOME /home/www/my_flask/venv; # 指向虛擬環境目錄 uwsgi_param UWSGI_CHDIR /home/www/my_flask; # 指向網站根目錄 uwsgi_param UWSGI_SCRIPT manage:app; # 指定啟動程序 } } |
將default配置文件替換掉就大功告成了!
還有,更改配置還需要記得重啟一下nginx:
1
|
sudo service nginx restart |
總結
阿里云的服務器運行速度很不錯,加上Flask+uWSGI+nginx 這種高性能結構,整個網站響應速度極為之快,每頁響應速度不到0.1s , 與之相比我之前使用 C# 部署在Avarix 上的網站(同一個程序,不同語言實現)每頁響應速度至少2s 這簡直是 200:1的性能,當然我還沒有閑到去專們用軟件去測這兩者之間的差值,寫本文的目的也是對此作一記錄,以便以后回顧。
原文鏈接:http://www.cnblogs.com/Ray-liang/p/4173923.html