更新時間:2016年09月13日17時35分 來源:傳智播客 瀏覽次數(shù):
引:Django是Python眾多web框架中提供功能最全最豐富的一個,那么我們在實際應(yīng)用中通常怎么去部署Django呢?下面我們就來看一看Django的部署方案有哪些。
1. Python web 程序的部署方法:
Django是采用python寫的web框架,我們先來看下python的web程序的9種部署方法:
· mod_python,這是apache內(nèi)置的模塊,很嚴(yán)重的依賴于mod_python編譯使用的python版本,和apache配套使用,不推薦;
· cgi,這個太old,不推薦,而且nginx不支持cgi方式,只能用lighttpd或者apache;
· fastcgi ,這個是目前流行最廣的做法,通過flup模塊來支持的,在nginx里對應(yīng)的配置指令是 fastcgi_pass;
· spawn-fcgi,這個是fastcgi多進(jìn)程管理程序,lighttpd安裝包附帶的,和flup效果一樣,區(qū)別是flup是 python代碼級引入,spawn-fcgi是外部程序,spawn-fcgi用途很廣,可以支持任意語言開發(fā)的代碼,php、python、perl,只要你代碼實現(xiàn)了fastcgi接口,它都可以幫你管理你的進(jìn)程;
· scgi,全名是Simple Common Gateway Interface,也是cgi的替代版本,scgi協(xié)議很簡單,和fastcgi差不多,只是沒有怎么推廣開來,nginx對應(yīng)的配置指令是scgi_pass,你想用就用,flup也支持;
· http,nginx使用proxy_pass轉(zhuǎn)發(fā),這個要求后端application必須內(nèi)置一個能處理高并發(fā)的http server,在python的web框架當(dāng)中,只能選擇tornado;
python程序員喜歡發(fā)明輪子,tornado除了是一個web framework之外,它還可以單獨提供高性能http server,所以,如果你采用其他python框架寫代碼,比如說bottle,也一樣可以通過import tornado 來啟動一個高性能的http server,同樣的可以采用http協(xié)議和nginx一起來部署。擴(kuò)展開來,python包里面能處理高并發(fā)的http server還有很多,比如說gevent,也可以被其他框架引用來支持http方式部署。
· uwsgi,包括4部分組成:
o uwsgi協(xié)議
o web server內(nèi)置支持協(xié)議模塊
o application服務(wù)器協(xié)議支持模塊
o 進(jìn)程控制程序
nginx從0.8.4開始內(nèi)置支持uwsgi協(xié)議,uwsgi協(xié)議非常簡單,一個4個字節(jié)header加一個body,body可以是很多協(xié)議的包,比如說http,cgi等(通過header里面字段標(biāo)示)。
uwsgi的特點在于自帶的進(jìn)程控制程序,它是用c語言編寫,使用natvie函數(shù),其實和spawn-fcgi/php-fpm類似。所以uwsgi可以支持多種應(yīng)用框架,包括(python、lua、ruby、erlang、go)等等
· Gunicorn,和uwsgi類似的工具,從rails的部署工具(Unicorn)移植過來的。但是它使用的協(xié)議是 WSGI,全稱是Python Web Server Gateway Interface ,這是python2.5時定義的官方標(biāo)準(zhǔn)(PEP 333 ),根紅苗正,而且部署比較簡單;
· mod_wsgi,apache的一個module,也是支持WSGI協(xié)議,https://code.google.com/p/modwsgi/
2. Nginx + uWSGI + Django
先來澄清幾個概念:
WSGI: WSGI是一種Web服務(wù)器網(wǎng)關(guān)接口。它是一個Web服務(wù)器(如nginx)與應(yīng)用服務(wù)器(如uWSGI服務(wù)器)通信的一種規(guī)范。
uwsgi: uwsgi同WSGI一樣是一種通信協(xié)議,而uWSGI是實現(xiàn)了uwsgi和WSGI兩種協(xié)議的Web服務(wù)器。
uwsgi協(xié)議是一個uWSGI服務(wù)器自有的協(xié)議,它用于定義傳輸信息的類型(type of information),每一個uwsgi packet前4byte為傳輸信息類型描述,它與WSGI相比是兩樣?xùn)|西。
uWSGI: uWSGI是一個Web服務(wù)器,它實現(xiàn)了WSGI協(xié)議、uwsgi、http等協(xié)議。 Nginx中HttpUwsgiModule的作用是與uWSGI服務(wù)器進(jìn)行交換。
uWSGI的主要特點如下:
超快的性能
低內(nèi)存占用(實測為apache2的mod_wsgi的一半左右)
多app管理
詳盡的日志功能(可以用來分析app性能和瓶頸)
高度可定制(內(nèi)存大小限制,服務(wù)一定次數(shù)后重啟等)
由于uWSGI有著上述優(yōu)點,通常采用Nginx + uWSGI + Django來部署,性能與穩(wěn)定性都不錯。
部署方法:
1 安裝uwsgi
pip install uwsgi
2 寫配置文件 yourfile.ini (文件名可自定義)
[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
processes = 4
threads = 2
master= True
pidfile = yourfile.pid
daemonize = yourfile.log
3 執(zhí)行 uwsgi yourfile.ini
4 nginx 配置
location / {
uwsgi_pass 127.0.0.1:8630;
include uwsgi_params;
}
3. Nginx + Tornado + Django
Tornado是一個異步web框架和服務(wù)器,所以在開發(fā)長輪詢的chat之類應(yīng)用非常的合適,但是其實本身也是一個高性能的http服務(wù)器,也可以作為一個WSGIServer。所以即使網(wǎng)站沒有使用Tornado的框架,而是用了web.py或者是Django來開發(fā), Tornado依然可以用來加速網(wǎng)站。使用Tornado來代替fastCGI可以大幅提高性能,且可以承載的并發(fā)能力也有了成倍的提高。
部署方法:
采用Nginx通過upstream來反向代理到N個Tornado的服務(wù)器實例上的部署方式。
Setp1:安裝supervisord
由于Tornado并沒有自身提供Daemon的能力,所以需要用一個服務(wù)管理工具來管理Tornado的進(jìn)程,supervisord是用Python實現(xiàn)的一款非常實用的進(jìn)程管理工具。可以很方便的管理N過進(jìn)程,且支持進(jìn)程分組。Supervisord可以通過sudo easy_install supervisor安裝,當(dāng)然也可以通過Supervisord官網(wǎng)下載后setup.py install安裝。
Step2: 給Django的站點增加一個Tornado的服務(wù)器文件(比如serv.py)
創(chuàng)建一個文件Serv.py在Django站點的根目錄(Django 1.4中應(yīng)該放到和urls.py同一級目錄),內(nèi)容如下:
import os
import sys
from tornado.options import options, define, parse_command_line
import django.core.handlers.wsgi
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.wsgi
HERE = os.path.dirname(os.path.abspath(file_))
sys.path.append(_HERE)
sys.path.append(os.path.join(_HERE, '..'))
sys.path.append(os.path.join(_HERE, '../contrib'))
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
def main(port):
wsgi_app = tornado.wsgi.WSGIContainer(
django.core.handlers.wsgi.WSGIHandler())
tornado_app = tornado.web.Application(
[('.*', tornado.web.FallbackHandler, dict(fallback=wsgi_app)),
])
server = tornado.httpserver.HTTPServer(tornado_app)
server.listen(port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == 'main':
main(int(sys.argv[1]))
我這里通過第一個參數(shù)來指定Tornado服務(wù)監(jiān)聽的端口。這樣比較靈活,這點我們在后面的步驟會用到。這個時候我們可以通過python Serv.py 8000這個命令來啟動服務(wù)器
Step3: 配置Supervisord
第一步安裝的Supervisord還沒有配置,所以我們需要先創(chuàng)建一個配置文件的樣板。在root權(quán)限下執(zhí)行echo_supervisord_conf > /etc/supervisord.conf這個時候在/etc/創(chuàng)建了配置文件,用vim打開這個文件,在配置文件的屁股后面加上以下這一段
[program:web]
command=python /var/www/site/Serv.py 80%(process_num)02d
process_name=%(program_name)s_%(process_num)02d
umask=022
startsecs=0
stopwaitsecs=0
redirect_stderr=true
stdout_logfile=/tmp/codoon.log
numprocs=4
numprocs_start=1
這個配置會啟動4個Tornado的服務(wù)進(jìn)程分別監(jiān)聽 8001,8002,8003,8004 這四個端口
command這一行是要執(zhí)行的命令,這里是用 python /var/www/site/Serv.py 端口號來啟動Tornado的服務(wù)進(jìn)程 80%(process_num)02d 的用途是通過進(jìn)程編號來生成端口號。下面的process_name這個參數(shù)也會用到。這里要指定的文件名就是上一步我們創(chuàng)建那個Serv.py文件
process_name是進(jìn)程的名字,由于這里要啟動4個進(jìn)程,所以要用process_num來區(qū)分
umask是程序執(zhí)行的權(quán)限參數(shù)
startsecs這個參數(shù)是程序啟動的等待時間
stopwaitsecs這個參數(shù)是程序停止的等待時間
redirect_stderr這個參數(shù)將錯誤流重定向到std的流輸出,這樣可以省去一個日志文件的配置,當(dāng)然也可以不用這個參數(shù)分開配置日志文件
stdout_logfile 這個參數(shù)是STD流輸出日志文件的路徑,Tornado會輸出所有的請求和錯誤信息,通過這個可以統(tǒng)一做日志處理,分隔什么的,在程序里就只需要print到std流就行了。
numprocs 這個參數(shù)指定了進(jìn)程的數(shù)量,這里是4,表明要啟動4個Tornado進(jìn)程
numprocs_start 這個參數(shù)指定了進(jìn)程號的起始編號,這里是1,這樣前面的command和process_name里的%(process_num)02d部分就會在執(zhí)行的時候被替換為01~05的字符串
配置修改完成后:wq保存退出,執(zhí)行:
supervisorctl reload
重新加載配置后,這些進(jìn)程就啟動起來了
Step4:修改配置Nginx
首先找到在vhost目錄里你的站點配置文件,打開后,在頭上增加upstream的內(nèi)容
upstream frontends {
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
server 127.0.0.1:8004;
}
然后在Server配置節(jié)里找到
location / { 這個配置節(jié)
以前是用的FastCGI,所以里面的配置可能是這樣子的
host and port to fastcgi server
fastcgi_pass 127.0.0.1:8081;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_pass_header Authorization;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_intercept_errors off;
把這些統(tǒng)統(tǒng)刪掉,變成了這樣
location / {
}
在{}中加入upstream的配置,變成如下樣子
location / {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass http://frontends;
proxy_next_upstream error;
}
保存配置文件后執(zhí)行 讓nginx重啟的指令 nginx -s reload(注意 nginx文件在不同發(fā)行版中位置有差別)