Python部署web開(kāi)發(fā)程序的幾種方法
1、fastcgi ,通過(guò)flup模塊來(lái)支持,在nginx里對(duì)應(yīng)的配置指令是 fastcgi_pass
2、http,nginx使用proxy_pass轉(zhuǎn)發(fā),這個(gè)要求后端appplication必須內(nèi)置一個(gè)能處理高并發(fā)的http server,在python的web框架當(dāng)中,只能選擇tornado.
3、uwsgi,包括4部分組成:
- uwsgi協(xié)議
- web server內(nèi)置支持協(xié)議模塊
- application服務(wù)器協(xié)議支持模塊
- 進(jìn)程控制程序
nginx從0.8.4開(kāi)始內(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ǔ)言編寫(xiě),使用natvie函數(shù),其實(shí)和spawn-fcgi/php-fpm類(lèi)似。所以u(píng)wsgi可以支持多種應(yīng)用框架,包括(python,lua,ruby,erlang,go)等等
4、mod_python,這是apache內(nèi)置的模塊,很?chē)?yán)重的依賴(lài)于mod_python編譯使用的python版本,和apache配套使用,不推薦
5、cgi,這個(gè)太old,不推薦,而且nginx不支持cgi方式,只能用lighttpd或者apache
6、spawn-fcgi,這個(gè)是fastcgi多進(jìn)程管理程序,lighttpd安裝包附帶的,和 flup效果一樣,區(qū)別是flup是 python代碼級(jí)引入,spawn-fcgi是外部程序。spawn-fcgi用途很廣,可以支持任意語(yǔ)言開(kāi)發(fā)的代碼,php,python,perl,只要你代碼實(shí)現(xiàn)了fastcgi接口,它都可以幫你管理你的進(jìn)程
7、scgi,全名是Simple Common Gateway Interface,也是cgi的替代版本,scgi協(xié)議很簡(jiǎn)單,我覺(jué)得和fastcgi差不多,只是沒(méi)有怎么推廣開(kāi)來(lái),nginx對(duì)應(yīng)的配置指令是scgi_pass,你想用就用,flup也支持。
8、Gunicorn,和uwsgi類(lèi)似的工具,從rails的部署工具(Unicorn)移植過(guò)來(lái)的。但是它使用的協(xié)議是 WSGI,全稱(chēng)是Python Web Server Gateway Interface ,這是python2.5時(shí)定義的官方標(biāo)準(zhǔn)(PEP 333 ),根紅苗正,而且部署比較簡(jiǎn)單,http://gunicorn.org/ 上有詳細(xì)教程
9、mod_wsgi,apache的一個(gè)module,也是支持WSGI協(xié)議,https://code.google.com/p/modwsgi/
uwsgi
安裝uwsgi
pip install uwsgi
配置uwsgi
uwsgi 有多種配置可用:
1,ini 2,xml 3,json 4,yaml
配置示例
$ cat etc/uwsgi.ini [uwsgi] socket = 127.0.0.1:9005 chdir = /Users/suoning/python_project/trunk/ wsgi-file = main.py processes = 4 stats = 127.0.0.1:9000 daemonize = /tmp/uwsgiServer.log pidfile = /tmp/uwsgi.pid vacuum = true log-maxsize = 50000000 disable-logging = true callable = app $
配置參數(shù)詳解:
常用選項(xiàng):
socket : 地址和端口號(hào),例如:socket = 127.0.0.1:50000
processes : 開(kāi)啟的進(jìn)程數(shù)量
workers : 開(kāi)啟的進(jìn)程數(shù)量,等同于processes(官網(wǎng)的說(shuō)法是spawn the specified number of workers / processes)
chdir : 指定運(yùn)行目錄(chdir to specified directory before apps loading)
wsgi-file : 載入wsgi-file(load .wsgi file)
stats : 在指定的地址上,開(kāi)啟狀態(tài)服務(wù)(enable the stats server on the specified address)
threads : 運(yùn)行線程。由于GIL的存在,我覺(jué)得這個(gè)真心沒(méi)啥用。(run each worker in prethreaded mode with the specified number of threads)
master : 允許主進(jìn)程存在(enable master process)
daemonize : 使進(jìn)程在后臺(tái)運(yùn)行,并將日志打到指定的日志文件或者udp服務(wù)器(daemonize uWSGI)。實(shí)際上最常用的,還是把運(yùn)行記錄輸出到一個(gè)本地文件上。
log-maxsize :以固定的文件大?。▎挝籏B),切割日志文件。 例如:log-maxsize = 50000000 就是50M一個(gè)日志文件。
pidfile : 指定pid文件的位置,記錄主進(jìn)程的pid號(hào)。
vacuum : 當(dāng)服務(wù)器退出的時(shí)候自動(dòng)清理環(huán)境,刪除unix socket文件和pid文件(try to remove all of the generated file/sockets)
disable-logging : 不記錄請(qǐng)求信息的日志。只記錄錯(cuò)誤以及uWSGI內(nèi)部消息到日志中。如果不開(kāi)啟這項(xiàng),那么你的日志中會(huì)大量出現(xiàn)這種記錄:
[pid: 347|app: 0|req: 106/367] 117.116.122.172 () {52 vars in 961 bytes} [Thu Jul 7 19:20:56 2016] POST /post => generated 65 bytes in 6 msecs (HTTP/1.1 200) 2 headers in 88 bytes (1 switches on core 0)
配置nginx
$ cat etc/nginx/servers/tongbupan.conf
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:9005;
}
location /webstatic/ {
expires 7d;
add_header Cache-Control public;
alias /Users/suoning/probject/python_project/webstatic/trunk/;
}
}
$
$ nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful
$
$ nginx -s reload
$
配置application
flask 示例
...
app = Flask('pan')
...
if __name__ == '__main__':
# app.run(host='0.0.0.0', port=5000)
app.run()
# 注意:變量app對(duì)應(yīng)uwsgi配置文件uwsgi.ini中 callable = app
啟動(dòng)uwsgi
$ $ uwsgi --ini /usr/local/etc/uwsgi.ini [uWSGI] getting INI configuration from /usr/local/etc/uwsgi.ini $ $ ps -ef|grep uwsgi 11428 1 0 11:40下午 ?? 0:01.23 uwsgi --ini /usr/local/etc/uwsgi.ini 11432 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini 11433 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini 11434 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini 11435 11428 0 11:40下午 ?? 0:00.00 uwsgi --ini /usr/local/etc/uwsgi.ini 11440 69240 0 11:40下午 ttys000 0:00.00 grep uwsgi $ $ lsof -i tcp:9000 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME uwsgi 11428 suoning 28u IPv4 0x5583e11534d24e73 0t0 TCP localhost:cslistener (LISTEN) $ $ lsof -i tcp:9005 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME uwsgi 11428 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN) uwsgi 11432 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN) uwsgi 11433 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN) uwsgi 11434 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN) uwsgi 11435 suoning 6u IPv4 0x5583e11535699e73 0t0 TCP localhost:9005 (LISTEN) $
FCGI
參考:http://webpy.org/cookbook/fastcgi-nginx
配置Nginx
$ cat etc/nginx/servers/pan.conf
server {
listen 80;
server_name localhost;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location / {
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_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_pass 127.0.0.1:9005;
}
location /webstatic/ {
expires 7d;
add_header Cache-Control public;
alias /Users/suoning/probject/python_project/webstatic/trunk/;
}
}
$
配置application
簡(jiǎn)單示例
from flup.server.fcgi import WSGIServer from pan import app WSGIServer( app, bindAddress=(host, port), maxThreads=threads ).run()
生產(chǎn)環(huán)境示例
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'suoning'
import sys
import argparse
from flup.server.fcgi import WSGIServer
from lib.daemon import Daemon
from pan import app
APP_NAME = 'pan_platform'
APP_INST_NAME = '20170501'
parser = argparse.ArgumentParser(description=u'Run an pan FastCGI server')
parser.add_argument('command', type=str,
help=u'command [start|stop|restart]',
choices=['start', 'stop', 'restart'])
parser.add_argument('-p', '--port', type=int,
help=u'port of this server', required=True)
parser.add_argument('-t', '--threads', type=int, default=50,
help=u'max number of threads')
parser.add_argument('-host', '--host', default='0.0.0.0',
help=u'Listen to the main clause')
class panPlatformDaemon(Daemon):
def run(self):
# 運(yùn)行服務(wù)
try:
WSGIServer(
app,
bindAddress=(args.host, args.port),
maxThreads=args.threads,
umask=0111
).run()
except:
sys.stderr.write('oops')
def gen_pidfile(port):
return '/var/run/%s_%s_%d.pid' % (APP_NAME, APP_INST_NAME, port)
if __name__ == '__main__':
args = parser.parse_args()
daemon = panPlatformDaemon(gen_pidfile(args.port))
if 'start' == args.command:
daemon.start()
elif 'stop' == args.command:
daemon.stop()
elif 'restart' == args.command:
daemon.restart()
else:
print "Unknown command"
sys.exit(2)
sys.exit(0)
fastcgi協(xié)議和http協(xié)議在代碼部署中的的優(yōu)劣對(duì)比
- fastcgi雖然是二進(jìn)制協(xié)議,相對(duì)于http協(xié)議,并不節(jié)省資源。二進(jìn)制協(xié)議,只能節(jié)省數(shù)字的表達(dá),比如 1234567,用字符串表示需要7個(gè)Byte,用數(shù)字就是4個(gè)Byte,而字符串到哪里都一樣
- fastcgi在傳輸數(shù)據(jù)的時(shí)候,為了兼容cgi協(xié)議,還要帶上一堆cgi的環(huán)境變量,所以和http協(xié)議相比,用fastcgi傳輸數(shù)據(jù)并不省,反而多一些
- fastcgi 唯一的優(yōu)點(diǎn)是,它是長(zhǎng)連接的,用戶(hù)并發(fā)1000個(gè)request,fastcgi可能就用10個(gè) 鏈接轉(zhuǎn)發(fā)給后端的appplication,如果用http協(xié)議,那來(lái)多少給多少,會(huì)向后端appplication 發(fā)起1000個(gè)請(qǐng)求
- http代理轉(zhuǎn)發(fā)方式,在面對(duì)超高并發(fā)的情況下會(huì)出問(wèn)題,因?yàn)?,tcp協(xié)議棧當(dāng)中,port是int16整型 你本地新建一個(gè)connect,需要消耗一個(gè)端口,最多能到65536。外部并發(fā)幾十萬(wàn)個(gè)請(qǐng)求,port池耗干,你的服務(wù)器只能拒絕響應(yīng)了
CGI, FCGI, SCGI, WSGI 區(qū)別
WIKI Links:
CGI - http://en.wikipedia.org/wiki/Common_Gateway_Interface
FCGI - http://en.wikipedia.org/wiki/Fcgi
SCGI - http://en.wikipedia.org/wiki/SCGI
WSGI - http://en.wikipedia.org/wiki/Wsgi
Other reference:
CGI = Common Gateway Interface
顧名思義,它是一種接口規(guī)范。該規(guī)范詳細(xì)定義了Web服務(wù)器中運(yùn)行的服務(wù)器代理程序,怎樣獲取及返回網(wǎng)頁(yè)生成過(guò)程中,服務(wù)器環(huán)境上下文和HTTP協(xié)議中的參數(shù)名稱(chēng),如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE等等。絕大部分的Web服務(wù)器程序,是以腳本的形式代理接受并處理HTTP請(qǐng)求,返回HTTP頁(yè)面或響應(yīng)。這些腳本程序,就是大家所熟知的PHP、ASP、JSP等等。
FCGI = Fast CGI
它其實(shí)是CGI在具體實(shí)現(xiàn)中的的一個(gè)變種。其設(shè)計(jì)思路是,通過(guò)減少CGI代理程序和Web宿主服務(wù)程序的通信開(kāi)銷(xiāo),從而達(dá)到提高Web服務(wù)性能的最終目的。由此可見(jiàn),F(xiàn)CGI在規(guī)范上跟CGI并沒(méi)有不同,只是具體實(shí)現(xiàn)方式上有所改進(jìn):CGI的做法是,對(duì)于每個(gè)HTTP請(qǐng)求,Web宿主服務(wù)程序都建立新的進(jìn)程以調(diào)用服務(wù)器腳本,相應(yīng)該請(qǐng)求;FCGI的做法是,建立一個(gè)獨(dú)立的FCGI服務(wù)程序進(jìn)程,和Web宿主服務(wù)程序進(jìn)程通信,F(xiàn)CGI服務(wù)進(jìn)程被一旦啟動(dòng)后,自己分配資源、創(chuàng)建線程響應(yīng)HTTP請(qǐng)求、并決定自身生命周期,從而大大降低了系統(tǒng)為了創(chuàng)建進(jìn)程而做出的資源開(kāi)銷(xiāo)?,F(xiàn)代流行的Web服務(wù)器程序,如PHP、ASP.Net,基本都是FCGI的實(shí)現(xiàn)。
SCGI = Simple CGI
它是FCGI在精簡(jiǎn)數(shù)據(jù)協(xié)議和響應(yīng)過(guò)程后的產(chǎn)物。其設(shè)計(jì)目的是為了適應(yīng)越來(lái)越多基于AJAX或REST的HTTP請(qǐng)求,而做出更快更簡(jiǎn)潔的應(yīng)答。并且SCGI約定,當(dāng)服務(wù)器返回對(duì)一個(gè)HTTP協(xié)議請(qǐng)求響應(yīng)后,立刻關(guān)閉該HTTP連接。所以不難看出,SCGI更加適合于普遍意義上SOA所提倡的“請(qǐng)求-忘記”這種通信模式。
WSGI = Web Server Gateway Interface
此協(xié)議是Python語(yǔ)言的專(zhuān)利,它定義了一組在Web服務(wù)宿主程序和HTTP響應(yīng)代理程序之間通信的普遍適用的接口。它的產(chǎn)生是因?yàn)镻ython程序員注意到,對(duì)于Web框架和Web宿主服務(wù)器程序間,有嚴(yán)重的耦合性,比如說(shuō),某些框架是針對(duì)Apache的mod_python設(shè)計(jì)的。于是,WSGI就定義了一套非常低級(jí)別的接口。常見(jiàn)的Python Web框架都實(shí)現(xiàn)了這個(gè)協(xié)議:如 CherryPy, Django, web.py, web2py, TurboGears, Tornado, Pylons, BlueBream, Google App Engine[dubious – discuss], Trac, Flask, Pyramid,等等.
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持腳本之家!
- 哪些是python中web開(kāi)發(fā)框架
- python開(kāi)發(fā)實(shí)例之python使用Websocket庫(kù)開(kāi)發(fā)簡(jiǎn)單聊天工具實(shí)例詳解(python+Websocket+JS)
- python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5中QWebEngineView內(nèi)嵌網(wǎng)頁(yè)與Python的數(shù)據(jù)交互傳參詳細(xì)方法實(shí)例
- python GUI庫(kù)圖形界面開(kāi)發(fā)之PyQt5瀏覽器控件QWebEngineView詳細(xì)使用方法
- python Django的web開(kāi)發(fā)實(shí)例(入門(mén))
- python Web開(kāi)發(fā)你要理解的WSGI & uwsgi詳解
- Python中SOAP項(xiàng)目的介紹及其在web開(kāi)發(fā)中的應(yīng)用
- 10款最好的Web開(kāi)發(fā)的 Python 框架
- Python Web框架Flask下網(wǎng)站開(kāi)發(fā)入門(mén)實(shí)例
- 全面解讀Python Web開(kāi)發(fā)框架Django
- Python開(kāi)發(fā)WebService系列教程之REST,web.py,eurasia,Django
- Python用來(lái)做Web開(kāi)發(fā)的優(yōu)勢(shì)有哪些
相關(guān)文章
如何讓利用Python+AI使靜態(tài)圖片動(dòng)起來(lái)
這篇文章主要介紹了如何讓利用Python+AI使靜態(tài)圖片動(dòng)起來(lái),基于的GAN生成對(duì)抗網(wǎng)絡(luò)圍繞主題實(shí)現(xiàn)靜態(tài)圖片動(dòng)起來(lái)的效果。具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06
pycharm社區(qū)版安裝django并創(chuàng)建一個(gè)簡(jiǎn)單項(xiàng)目的全過(guò)程
社區(qū)版的pycharm跟專(zhuān)業(yè)版的pycharm應(yīng)用差別還是不太大,下面這篇文章主要給大家介紹了關(guān)于pycharm社區(qū)版安裝django并創(chuàng)建一個(gè)簡(jiǎn)單項(xiàng)目的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
Python中不可變數(shù)據(jù)類(lèi)型原理與實(shí)戰(zhàn)全解析
在Python的世界里,數(shù)據(jù)對(duì)象被明確劃分為兩大陣營(yíng):可變(Mutable)與不可變(Immutable),而本文將為大家詳細(xì)介紹一下其中的不可變數(shù)據(jù),感興趣的可以了解下2025-04-04
Python 由字符串函數(shù)名得到對(duì)應(yīng)的函數(shù)(實(shí)例講解)
下面小編就為大家?guī)?lái)一篇Python 由字符串函數(shù)名得到對(duì)應(yīng)的函數(shù)(實(shí)例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08
python如何調(diào)用現(xiàn)有的matlab函數(shù)
這篇文章主要介紹了python如何調(diào)用現(xiàn)有的matlab函數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
Python如何優(yōu)雅的實(shí)現(xiàn)自增枚舉類(lèi)
枚舉類(lèi)型在編程中扮演著重要的角色,它們?yōu)樽兞抠x予了更加清晰的含義,然而,在Python中,實(shí)現(xiàn)自增的枚舉類(lèi)并非直接而簡(jiǎn)單的任務(wù),本文將深入討論如何通過(guò)不同的方式優(yōu)雅地實(shí)現(xiàn)自增的枚舉類(lèi),需要的朋友可以參考下2023-12-12
Python?Pygame實(shí)戰(zhàn)之打磚塊小游戲
打磚塊最早是由雅達(dá)利公司開(kāi)發(fā)的一款獨(dú)立游戲,也是無(wú)數(shù)人的童年記憶。本文將利用Python中的Pygame模塊制作經(jīng)典的打磚塊游戲,需要的可以參考一下2022-02-02

