Python部署web开发程序的几种方法
1、fastcgi,通过flup模块来支持,在nginx里对应的配置指令是fastcgi_pass
2、http,nginx使用proxy_pass转发,这个要求后端appplication必须内置一个能处理高并发的httpserver,在python的web框架当中,只能选择tornado.
3、uwsgi,包括4部分组成:
- uwsgi协议
- webserver内置支持协议模块
- application服务器协议支持模块
- 进程控制程序
nginx从0.8.4开始内置支持uwsgi协议,uwsgi协议非常简单,一个4个字节header+一个body,body可以是很多协议的包,比如说http,cgi等(通过header里面字段标示)。
uwsgi的特点在于自带的进程控制程序.它是用c语言编写,使用natvie函数,其实和spawn-fcgi/php-fpm类似。所以uwsgi可以支持多种应用框架,包括(python,lua,ruby,erlang,go)等等
4、mod_python,这是apache内置的模块,很严重的依赖于mod_python编译使用的python版本,和apache配套使用,不推荐
5、cgi,这个太old,不推荐,而且nginx不支持cgi方式,只能用lighttpd或者apache
6、spawn-fcgi,这个是fastcgi多进程管理程序,lighttpd安装包附带的,和flup效果一样,区别是flup是python代码级引入,spawn-fcgi是外部程序。spawn-fcgi用途很广,可以支持任意语言开发的代码,php,python,perl,只要你代码实现了fastcgi接口,它都可以帮你管理你的进程
7、scgi,全名是SimpleCommonGatewayInterface,也是cgi的替代版本,scgi协议很简单,我觉得和fastcgi差不多,只是没有怎么推广开来,nginx对应的配置指令是scgi_pass,你想用就用,flup也支持。
8、Gunicorn,和uwsgi类似的工具,从rails的部署工具(Unicorn)移植过来的。但是它使用的协议是WSGI,全称是PythonWebServerGatewayInterface,这是python2.5时定义的官方标准(PEP333),根红苗正,而且部署比较简单,http://gunicorn.org/上有详细教程
9、mod_wsgi,apache的一个module,也是支持WSGI协议,https://code.google.com/p/modwsgi/
uwsgi
安装uwsgi
pipinstalluwsgi
配置uwsgi
uwsgi有多种配置可用:
1,ini 2,xml 3,json 4,yaml
配置示例
$catetc/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 $
配置参数详解:
常用选项:
socket:地址和端口号,例如:socket=127.0.0.1:50000
processes:开启的进程数量
workers:开启的进程数量,等同于processes(官网的说法是spawnthespecifiednumberof workers/processes)
chdir:指定运行目录(chdirtospecifieddirectorybeforeappsloading)
wsgi-file:载入wsgi-file(load.wsgifile)
stats:在指定的地址上,开启状态服务(enablethestatsserveronthespecifiedaddress)
threads:运行线程。由于GIL的存在,我觉得这个真心没啥用。(runeachworkerinprethreadedmodewiththespecifiednumberofthreads)
master:允许主进程存在(enablemasterprocess)
daemonize:使进程在后台运行,并将日志打到指定的日志文件或者udp服务器(daemonizeuWSGI)。实际上最常用的,还是把运行记录输出到一个本地文件上。
log-maxsize:以固定的文件大小(单位KB),切割日志文件。例如:log-maxsize=50000000 就是50M一个日志文件。
pidfile:指定pid文件的位置,记录主进程的pid号。
vacuum:当服务器退出的时候自动清理环境,删除unixsocket文件和pid文件(trytoremoveallofthegeneratedfile/sockets)
disable-logging:不记录请求信息的日志。只记录错误以及uWSGI内部消息到日志中。如果不开启这项,那么你的日志中会大量出现这种记录:
[pid:347|app:0|req:106/367]117.116.122.172(){52varsin961bytes}[ThuJul 719:20:562016]POST/post=>generated65bytesin6msecs(HTTP/1.1200)2headersin88bytes(1switchesoncore0)
配置nginx
$catetc/nginx/servers/tongbupan.conf server{ listen80; server_namelocalhost; location/{ includeuwsgi_params; uwsgi_pass127.0.0.1:9005; } location/webstatic/{ expires7d; add_headerCache-Controlpublic; alias/Users/suoning/probject/python_project/webstatic/trunk/; } } $ $nginx-t nginx:theconfigurationfile/usr/local/etc/nginx/nginx.confsyntaxisok nginx:configurationfile/usr/local/etc/nginx/nginx.conftestissuccessful $ $nginx-sreload $
配置application
flask示例
... app=Flask('pan') ... if__name__=='__main__': #app.run(host='0.0.0.0',port=5000) app.run() #注意:变量app对应uwsgi配置文件uwsgi.ini中callable=app
启动uwsgi
$ $uwsgi--ini/usr/local/etc/uwsgi.ini [uWSGI]gettingINIconfigurationfrom/usr/local/etc/uwsgi.ini $ $ps-ef|grepuwsgi 114281011:40下午??0:01.23uwsgi--ini/usr/local/etc/uwsgi.ini 1143211428011:40下午??0:00.00uwsgi--ini/usr/local/etc/uwsgi.ini 1143311428011:40下午??0:00.00uwsgi--ini/usr/local/etc/uwsgi.ini 1143411428011:40下午??0:00.00uwsgi--ini/usr/local/etc/uwsgi.ini 1143511428011:40下午??0:00.00uwsgi--ini/usr/local/etc/uwsgi.ini 1144069240011:40下午ttys0000:00.00grepuwsgi $ $lsof-itcp:9000 COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAME uwsgi11428suoning28uIPv40x5583e11534d24e730t0TCPlocalhost:cslistener(LISTEN) $ $lsof-itcp:9005 COMMANDPIDUSERFDTYPEDEVICESIZE/OFFNODENAME uwsgi11428suoning6uIPv40x5583e11535699e730t0TCPlocalhost:9005(LISTEN) uwsgi11432suoning6uIPv40x5583e11535699e730t0TCPlocalhost:9005(LISTEN) uwsgi11433suoning6uIPv40x5583e11535699e730t0TCPlocalhost:9005(LISTEN) uwsgi11434suoning6uIPv40x5583e11535699e730t0TCPlocalhost:9005(LISTEN) uwsgi11435suoning6uIPv40x5583e11535699e730t0TCPlocalhost:9005(LISTEN) $
FCGI
参考:http://webpy.org/cookbook/fastcgi-nginx
配置Nginx
$catetc/nginx/servers/pan.conf server{ listen80; server_namelocalhost; error_page500502503504/50x.html; location=/50x.html{ roothtml; } location/{ fastcgi_paramREQUEST_METHOD$request_method; fastcgi_paramQUERY_STRING$query_string; fastcgi_paramCONTENT_TYPE$content_type; fastcgi_paramCONTENT_LENGTH$content_length; fastcgi_paramGATEWAY_INTERFACECGI/1.1; fastcgi_paramSERVER_SOFTWAREnginx/$nginx_version; fastcgi_paramREMOTE_ADDR$remote_addr; fastcgi_paramREMOTE_PORT$remote_port; fastcgi_paramSERVER_ADDR$server_addr; fastcgi_paramSERVER_PORT$server_port; fastcgi_paramSERVER_NAME$server_name; fastcgi_paramSERVER_PROTOCOL$server_protocol; fastcgi_paramSCRIPT_FILENAME$fastcgi_script_name; fastcgi_paramPATH_INFO$fastcgi_script_name; fastcgi_pass127.0.0.1:9005; } location/webstatic/{ expires7d; add_headerCache-Controlpublic; alias/Users/suoning/probject/python_project/webstatic/trunk/; } } $
配置application
简单示例
fromflup.server.fcgiimportWSGIServer frompanimportapp WSGIServer( app, bindAddress=(host,port), maxThreads=threads ).run()
生产环境示例
#!/usr/bin/envpython #-*-coding:utf-8-*- __author__='suoning' importsys importargparse fromflup.server.fcgiimportWSGIServer fromlib.daemonimportDaemon frompanimportapp APP_NAME='pan_platform' APP_INST_NAME='20170501' parser=argparse.ArgumentParser(description=u'RunanpanFastCGIserver') 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'portofthisserver',required=True) parser.add_argument('-t','--threads',type=int,default=50, help=u'maxnumberofthreads') parser.add_argument('-host','--host',default='0.0.0.0', help=u'Listentothemainclause') classpanPlatformDaemon(Daemon): defrun(self): #运行服务 try: WSGIServer( app, bindAddress=(args.host,args.port), maxThreads=args.threads, umask=0111 ).run() except: sys.stderr.write('oops') defgen_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"Unknowncommand" sys.exit(2) sys.exit(0)
fastcgi协议和http协议在代码部署中的的优劣对比
- fastcgi虽然是二进制协议,相对于http协议,并不节省资源。二进制协议,只能节省数字的表达,比如1234567,用字符串表示需要7个Byte,用数字就是4个Byte,而字符串到哪里都一样
- fastcgi在传输数据的时候,为了兼容cgi协议,还要带上一堆cgi的环境变量,所以和http协议相比,用fastcgi传输数据并不省,反而多一些
- fastcgi唯一的优点是,它是长连接的,用户并发1000个request,fastcgi可能就用10个链接转发给后端的appplication,如果用http协议,那来多少给多少,会向后端appplication发起1000个请求
- http代理转发方式,在面对超高并发的情况下会出问题,因为,tcp协议栈当中,port是int16整型你本地新建一个connect,需要消耗一个端口,最多能到65536。外部并发几十万个请求,port池耗干,你的服务器只能拒绝响应了
CGI,FCGI,SCGI,WSGI区别
WIKILinks:
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
Otherreference:
http://helpful.knobs-dials.com/index.php/CGI%2C_FastCGI%2C_SCGI%2C_WSGI%2C_servlets_and_such#FastCGI_and_SCGI
CGI=CommonGatewayInterface
顾名思义,它是一种接口规范。该规范详细定义了Web服务器中运行的服务器代理程序,怎样获取及返回网页生成过程中,服务器环境上下文和HTTP协议中的参数名称,如大家所熟知的:REQUEST_METHOD,QUERY_STRING,CONTENT_TYPE等等。绝大部分的Web服务器程序,是以脚本的形式代理接受并处理HTTP请求,返回HTTP页面或响应。这些脚本程序,就是大家所熟知的PHP、ASP、JSP等等。
FCGI=FastCGI
它其实是CGI在具体实现中的的一个变种。其设计思路是,通过减少CGI代理程序和Web宿主服务程序的通信开销,从而达到提高Web服务性能的最终目的。由此可见,FCGI在规范上跟CGI并没有不同,只是具体实现方式上有所改进:CGI的做法是,对于每个HTTP请求,Web宿主服务程序都建立新的进程以调用服务器脚本,相应该请求;FCGI的做法是,建立一个独立的FCGI服务程序进程,和Web宿主服务程序进程通信,FCGI服务进程被一旦启动后,自己分配资源、创建线程响应HTTP请求、并决定自身生命周期,从而大大降低了系统为了创建进程而做出的资源开销。现代流行的Web服务器程序,如PHP、ASP.Net,基本都是FCGI的实现。
SCGI=SimpleCGI
它是FCGI在精简数据协议和响应过程后的产物。其设计目的是为了适应越来越多基于AJAX或REST的HTTP请求,而做出更快更简洁的应答。并且SCGI约定,当服务器返回对一个HTTP协议请求响应后,立刻关闭该HTTP连接。所以不难看出,SCGI更加适合于普遍意义上SOA所提倡的“请求-忘记”这种通信模式。
WSGI=WebServerGatewayInterface
此协议是Python语言的专利,它定义了一组在Web服务宿主程序和HTTP响应代理程序之间通信的普遍适用的接口。它的产生是因为Python程序员注意到,对于Web框架和Web宿主服务器程序间,有严重的耦合性,比如说,某些框架是针对Apache的mod_python设计的。于是,WSGI就定义了一套非常低级别的接口。常见的PythonWeb框架都实现了这个协议:如CherryPy,Django,web.py,web2py,TurboGears,Tornado,Pylons,BlueBream,GoogleAppEngine[dubious–discuss],Trac,Flask,Pyramid,等等.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!