更新時(shí)間:2016年09月13日17時(shí)35分 來(lái)源:傳智播客 瀏覽次數(shù):
引:Django是Python眾多web框架中提供功能最全最豐富的一個(gè),那么我們?cè)趯?shí)際應(yīng)用中通常怎么去部署Django呢?下面我們就來(lái)看一看Django的部署方案有哪些。
1. Python web 程序的部署方法:
Django是采用python寫的web框架,我們先來(lái)看下python的web程序的9種部署方法:
· mod_python,這是apache內(nèi)置的模塊,很嚴(yán)重的依賴于mod_python編譯使用的python版本,和apache配套使用,不推薦;
· cgi,這個(gè)太old,不推薦,而且nginx不支持cgi方式,只能用lighttpd或者apache;
· fastcgi ,這個(gè)是目前流行最廣的做法,通過(guò)flup模塊來(lái)支持的,在nginx里對(duì)應(yīng)的配置指令是 fastcgi_pass;
· spawn-fcgi,這個(gè)是fastcgi多進(jìn)程管理程序,lighttpd安裝包附帶的,和flup效果一樣,區(qū)別是flup是 python代碼級(jí)引入,spawn-fcgi是外部程序,spawn-fcgi用途很廣,可以支持任意語(yǔ)言開發(fā)的代碼,php、python、perl,只要你代碼實(shí)現(xiàn)了fastcgi接口,它都可以幫你管理你的進(jìn)程;
· scgi,全名是Simple Common Gateway Interface,也是cgi的替代版本,scgi協(xié)議很簡(jiǎn)單,和fastcgi差不多,只是沒(méi)有怎么推廣開來(lái),nginx對(duì)應(yīng)的配置指令是scgi_pass,你想用就用,flup也支持;
· http,nginx使用proxy_pass轉(zhuǎn)發(fā),這個(gè)要求后端application必須內(nèi)置一個(gè)能處理高并發(fā)的http server,在python的web框架當(dāng)中,只能選擇tornado;
python程序員喜歡發(fā)明輪子,tornado除了是一個(gè)web framework之外,它還可以單獨(dú)提供高性能http server,所以,如果你采用其他python框架寫代碼,比如說(shuō)bottle,也一樣可以通過(guò)import tornado 來(lái)啟動(dòng)一個(gè)高性能的http server,同樣的可以采用http協(xié)議和nginx一起來(lái)部署。擴(kuò)展開來(lái),python包里面能處理高并發(fā)的http server還有很多,比如說(shuō)gevent,也可以被其他框架引用來(lái)支持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é)議非常簡(jiǎn)單,一個(gè)4個(gè)字節(jié)header加一個(gè)body,body可以是很多協(xié)議的包,比如說(shuō)http,cgi等(通過(guò)header里面字段標(biāo)示)。
uwsgi的特點(diǎn)在于自帶的進(jìn)程控制程序,它是用c語(yǔ)言編寫,使用natvie函數(shù),其實(shí)和spawn-fcgi/php-fpm類似。所以u(píng)wsgi可以支持多種應(yīng)用框架,包括(python、lua、ruby、erlang、go)等等
· Gunicorn,和uwsgi類似的工具,從rails的部署工具(Unicorn)移植過(guò)來(lái)的。但是它使用的協(xié)議是 WSGI,全稱是Python Web Server Gateway Interface ,這是python2.5時(shí)定義的官方標(biāo)準(zhǔn)(PEP 333 ),根紅苗正,而且部署比較簡(jiǎn)單;
· mod_wsgi,apache的一個(gè)module,也是支持WSGI協(xié)議,https://code.google.com/p/modwsgi/
2. Nginx + uWSGI + Django
先來(lái)澄清幾個(gè)概念:
WSGI: WSGI是一種Web服務(wù)器網(wǎng)關(guān)接口。它是一個(gè)Web服務(wù)器(如nginx)與應(yīng)用服務(wù)器(如uWSGI服務(wù)器)通信的一種規(guī)范。
uwsgi: uwsgi同WSGI一樣是一種通信協(xié)議,而uWSGI是實(shí)現(xiàn)了uwsgi和WSGI兩種協(xié)議的Web服務(wù)器。
uwsgi協(xié)議是一個(gè)uWSGI服務(wù)器自有的協(xié)議,它用于定義傳輸信息的類型(type of information),每一個(gè)uwsgi packet前4byte為傳輸信息類型描述,它與WSGI相比是兩樣?xùn)|西。
uWSGI: uWSGI是一個(gè)Web服務(wù)器,它實(shí)現(xiàn)了WSGI協(xié)議、uwsgi、http等協(xié)議。 Nginx中HttpUwsgiModule的作用是與uWSGI服務(wù)器進(jìn)行交換。
uWSGI的主要特點(diǎn)如下:
超快的性能
低內(nèi)存占用(實(shí)測(cè)為apache2的mod_wsgi的一半左右)
多app管理
詳盡的日志功能(可以用來(lái)分析app性能和瓶頸)
高度可定制(內(nèi)存大小限制,服務(wù)一定次數(shù)后重啟等)
由于uWSGI有著上述優(yōu)點(diǎn),通常采用Nginx + uWSGI + Django來(lái)部署,性能與穩(wěn)定性都不錯(cuò)。
部署方法:
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是一個(gè)異步web框架和服務(wù)器,所以在開發(fā)長(zhǎng)輪詢的chat之類應(yīng)用非常的合適,但是其實(shí)本身也是一個(gè)高性能的http服務(wù)器,也可以作為一個(gè)WSGIServer。所以即使網(wǎng)站沒(méi)有使用Tornado的框架,而是用了web.py或者是Django來(lái)開發(fā), Tornado依然可以用來(lái)加速網(wǎng)站。使用Tornado來(lái)代替fastCGI可以大幅提高性能,且可以承載的并發(fā)能力也有了成倍的提高。
部署方法:
采用Nginx通過(guò)upstream來(lái)反向代理到N個(gè)Tornado的服務(wù)器實(shí)例上的部署方式。
Setp1:安裝supervisord
由于Tornado并沒(méi)有自身提供Daemon的能力,所以需要用一個(gè)服務(wù)管理工具來(lái)管理Tornado的進(jìn)程,supervisord是用Python實(shí)現(xiàn)的一款非常實(shí)用的進(jìn)程管理工具??梢院芊奖愕墓芾鞱過(guò)進(jìn)程,且支持進(jìn)程分組。Supervisord可以通過(guò)sudo easy_install supervisor安裝,當(dāng)然也可以通過(guò)Supervisord官網(wǎng)下載后setup.py install安裝。
Step2: 給Django的站點(diǎn)增加一個(gè)Tornado的服務(wù)器文件(比如serv.py)
創(chuàng)建一個(gè)文件Serv.py在Django站點(diǎn)的根目錄(Django 1.4中應(yīng)該放到和urls.py同一級(jí)目錄),內(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]))
我這里通過(guò)第一個(gè)參數(shù)來(lái)指定Tornado服務(wù)監(jiān)聽的端口。這樣比較靈活,這點(diǎn)我們?cè)诤竺娴牟襟E會(huì)用到。這個(gè)時(shí)候我們可以通過(guò)python Serv.py 8000這個(gè)命令來(lái)啟動(dòng)服務(wù)器
Step3: 配置Supervisord
第一步安裝的Supervisord還沒(méi)有配置,所以我們需要先創(chuàng)建一個(gè)配置文件的樣板。在root權(quán)限下執(zhí)行echo_supervisord_conf > /etc/supervisord.conf這個(gè)時(shí)候在/etc/創(chuàng)建了配置文件,用vim打開這個(gè)文件,在配置文件的屁股后面加上以下這一段
[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
這個(gè)配置會(huì)啟動(dòng)4個(gè)Tornado的服務(wù)進(jìn)程分別監(jiān)聽 8001,8002,8003,8004 這四個(gè)端口
command這一行是要執(zhí)行的命令,這里是用 python /var/www/site/Serv.py 端口號(hào)來(lái)啟動(dòng)Tornado的服務(wù)進(jìn)程 80%(process_num)02d 的用途是通過(guò)進(jìn)程編號(hào)來(lái)生成端口號(hào)。下面的process_name這個(gè)參數(shù)也會(huì)用到。這里要指定的文件名就是上一步我們創(chuàng)建那個(gè)Serv.py文件
process_name是進(jìn)程的名字,由于這里要啟動(dòng)4個(gè)進(jìn)程,所以要用process_num來(lái)區(qū)分
umask是程序執(zhí)行的權(quán)限參數(shù)
startsecs這個(gè)參數(shù)是程序啟動(dòng)的等待時(shí)間
stopwaitsecs這個(gè)參數(shù)是程序停止的等待時(shí)間
redirect_stderr這個(gè)參數(shù)將錯(cuò)誤流重定向到std的流輸出,這樣可以省去一個(gè)日志文件的配置,當(dāng)然也可以不用這個(gè)參數(shù)分開配置日志文件
stdout_logfile 這個(gè)參數(shù)是STD流輸出日志文件的路徑,Tornado會(huì)輸出所有的請(qǐng)求和錯(cuò)誤信息,通過(guò)這個(gè)可以統(tǒng)一做日志處理,分隔什么的,在程序里就只需要print到std流就行了。
numprocs 這個(gè)參數(shù)指定了進(jìn)程的數(shù)量,這里是4,表明要啟動(dòng)4個(gè)Tornado進(jìn)程
numprocs_start 這個(gè)參數(shù)指定了進(jìn)程號(hào)的起始編號(hào),這里是1,這樣前面的command和process_name里的%(process_num)02d部分就會(huì)在執(zhí)行的時(shí)候被替換為01~05的字符串
配置修改完成后:wq保存退出,執(zhí)行:
supervisorctl reload
重新加載配置后,這些進(jìn)程就啟動(dòng)起來(lái)了
Step4:修改配置Nginx
首先找到在vhost目錄里你的站點(diǎn)配置文件,打開后,在頭上增加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 / { 這個(gè)配置節(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ā)行版中位置有差別)
北京校區(qū)