仓酷云

标题: 带来一篇多套计划来进步python web框架的并发处置才能 [打印本页]

作者: 爱飞    时间: 2015-1-14 20:30
标题: 带来一篇多套计划来进步python web框架的并发处置才能
如果您觉得本篇CentOSLinux教程讲得好,请记得点击右边漂浮的分享程序,把好文章分享给你的小伙伴们!Python罕见安排***有:
fcgi:用spawn-fcgi大概框架自带的工具对各个project分离天生监听历程,然后和http办事互动
wsgi:使用http办事的mod_wsgi模块来跑各个project(Web使用步伐或框架复杂而通用的Web办事器之间的接口)。
uWSGI是一款像php-cgi一样监听统一端口,举行一致办理和负载均衡的工具,uWSGI,既不必wsgi协定也不必fcgi协定,而是自创了一个uwsgi的协定,听说该协定约莫是fcgi协定的10倍那末快。


实在WSGI是分红server和framework(即application)两局部(固然另有middleware)。严厉说WSGI只是一个协定,标准server和framework之间毗连的接口。

WSGIserver把办事器功效以WSGI接口表露出来。好比mod_wsgi是一种server,把apache的功效以WSGI接口的情势供应出来。

1
2
3
4
5
WSGIframework就是我们常常提到的Django这类框架。不外必要注重的是,很少有纯真的WSGIframework,基于WSGI的框架常常都自带WSGIserver。好比Django、CherryPy都自带WSGIserver次要是测试用处,公布时则利用临盆情况的WSGIserver。而有些WSGI下的框架好比pylons、bfg等,本人不完成WSGIserver。利用paste作为WSGIserver。
Paste是盛行的WSGIserver,带有良多两头件。另有flup也是一个供应两头件的库。
弄扫除WSGIserver和application,两头件天然就分明了。除session、cache之类的使用,前段工夫看到一个bfg下的两头件专门用于给网站换肤的(skin)。两头件能够想到的用法还良多。
这里再增补一下,像django如许的框架怎样以fastcgi的体例跑在apache上的。这要用到flup.fcgi大概fastcgi.py(eurasia中也计划了一个fastcgi.py的完成)这些工具,它们就是把fastcgi协定转换成WSGI接口(把fastcgi酿成一个WSGIserver)供框架接进。全部架构是如许的:django->fcgi2wsgiserver->mod_fcgi->apache。
固然我不是WSGI的粉丝,可是不成否定WSGI对pythonweb的意义严重。成心本人计划web框架,又不想做socket层和http报文剖析的同砚,能够从WSGI入手下手计划本人的框架。在python圈子里有个共鸣,本人顺手弄个web框架跟喝口水一样天然,十分便利。也许每一个python玩家城市履历一个捣腾框架的




uWSGI的次要特性以下:
超快的功能。
低内存占用(实测为apache2的mod_wsgi的一半摆布)。
多app办理。
细致的日记功效(能够用来剖析app功能和瓶颈)。
高度可定制(内存巨细限定,办事必定次数后重启等)。


uwsgi的官方文档:
http://projects.unbit.it/uwsgi/wiki/Doc

nginx.conf

location/{
includeuwsgi_params
uwsgi_pass127.0.0.1:9090
}



启动app

uwsgi-s:9090-wmyapp




uwsgi的调优参数~

uwsgi的参数
以上是单个project的最复杂化安排,uwsgi仍是有良多使人夸奖的功效的,比方:
并发4个线程:
uwsgi-s:9090-wmyapp-p4
主把持线程+4个线程:
uwsgi-s:9090-wmyapp-M-p4
实行凌驾30秒的client间接保持:
uwsgi-s:9090-wmyapp-M-p4-t30
限定内存空间128M:
uwsgi-s:9090-wmyapp-M-p4-t30--limit-as128
办事凌驾10000个req主动respawn:
uwsgi-s:9090-wmyapp-M-p4-t30--limit-as128-R10000
背景运转等:
uwsgi-s:9090-wmyapp-M-p4-t30--limit-as128-R10000-duwsgi.log





为了让多个站点同享一个uwsgi办事,必需把uwsgi运转成假造站点:往失落“-wmyapp”加上”–vhost”:

uwsgi-s:9090-M-p4-t30--limit-as128-R10000-duwsgi.log--vhost
然后必需设置virtualenv,virtualenv是Python的一个很有效的假造情况工具,如许装置:


最初设置nginx,注重每一个站点必需独自占用一个server,统一server分歧location定向到分歧的使用不知为什么老是失利,估量也算是一个bug。
server{
listen80;
server_nameapp1.mydomain.com;
location/{
includeuwsgi_params;
uwsgi_pass127.0.0.1:9090;
uwsgi_paramUWSGI_PYHOME/var/www/myenv;
uwsgi_paramUWSGI_SCRIPTmyapp1;
uwsgi_paramUWSGI_CHDIR/var/www/myappdir1;
}
}
server{
listen80;
server_nameapp2.mydomain.com;
location/{
includeuwsgi_params;
uwsgi_pass127.0.0.1:9090;
uwsgi_paramUWSGI_PYHOME/var/www/myenv;
uwsgi_paramUWSGI_SCRIPTmyapp2;
uwsgi_paramUWSGI_CHDIR/var/www/myappdir2;
}
}




如许,重启nginx办事,两个站点就能够共用一个uwsgi办事了。

再来弄下fastcgi的体例



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:9002;
}





location/static/{
root/path/to/www;
if(-f$request_filename){
rewrite^/static/(.*)$/static/$1break;
}
}




启动一个fastcgi的历程


1
spawn-fcgi-d/path/to/www-f/path/to/www/index.py-a127.0.0.1-p9002




用web.py写的一个小demo测试


#!/usr/bin/envpython
#-*-coding:utf-8-*-
importweb
urls=("/.*","hello")
app=web.application(urls,globals())
classhello:
defGET(self):
returnHello,world!
if__name__=="__main__":
web.wsgi.runwsgi=lambdafunc,addr=None:web.wsgi.runfcgi(func,addr)
app.run()




启动nginx

nginx



如许就ok了~


上面入手下手先容下我一样平常用的***:




前端nginx用卖力负载分发:

安排的时分接纳了单IP多端口体例,办事器有4个中心,决意开4个端口对应,分离是8885~8888,修正



upstreambackend{
server127.0.0.1:8888;
server127.0.0.1:8887;
server127.0.0.1:8886;
server127.0.0.1:8885;
}
server{
listen80;
server_namemessage.test.com;
keepalive_timeout65;#
proxy_read_timeout2000;#
sendfileon;
tcp_nopushon;
tcp_nodelayon;
location/{
proxy_pass_headerServer;
proxy_set_headerHost$http_host;
proxy_redirectoff;
proxy_set_headerX-Real-IP$remote_addr;
proxy_set_headerX-Scheme$scheme;
proxy_passhttp://backend;
}
}




然后运转四个python步伐,端口为我们设置好的端口
我这里用tornado写了一个实行体系步伐的例子:


importsubprocess
importtornado.ioloop
importtime
importfcntl
importfunctools
importos
classGenericSubprocess(object):
def__init__(self,timeout=-1,**popen_args):
self.args=dict()
self.args["stdout"]=subprocess.PIPE
self.args["stderr"]=subprocess.PIPE
self.args["close_fds"]=True
self.args.update(popen_args)
self.ioloop=None
self.expiration=None
self.pipe=None
self.timeout=timeout
self.streams=[]
self.has_timed_out=False
defstart(self):
"""Spawnthetask.
ThrowsRuntimeErrorifthetaskwasalreadystarted."""
ifnotself.pipeisNone:
raiseRuntimeError("Cannotstarttasktwice")
self.ioloop=tornado.ioloop.IOLoop.instance()
ifself.timeout>0:
self.expiration=self.ioloop.add_timeout(time.time()+self.timeout,self.on_timeout)
self.pipe=subprocess.Popen(**self.args)
self.streams=[(self.pipe.stdout.fileno(),[]),
(self.pipe.stderr.fileno(),[])]
forfd,dinself.streams:
flags=fcntl.fcntl(fd,fcntl.F_GETFL)|os.O_NDELAY
fcntl.fcntl(fd,fcntl.F_SETFL,flags)
self.ioloop.add_handler(fd,
self.stat,
self.ioloop.READ|self.ioloop.ERROR)
defon_timeout(self):
self.has_timed_out=True
self.cancel()
defcancel(self):
"""Canceltaskexecution
SendsSIGKILLtothechildprocess."""
try:
self.pipe.kill()
except:
pass
defstat(self,*args):
CheckprocesscompletionandconsumependingI/Odata
self.pipe.poll()
ifnotself.pipe.returncodeisNone:
cleanuphandlersandtimeouts
ifnotself.expirationisNone:
self.ioloop.remove_timeout(self.expiration)
forfd,destinself.streams:
self.ioloop.remove_handler(fd)
schedullecallback(firsttrytoreadallpendingdata)
self.ioloop.add_callback(self.on_finish)
forfd,destinself.streams:
whileTrue:
try:
data=os.read(fd,4096)
iflen(data)==0:
break
dest.extend([data])
except:
break
@property
defstdout(self):
returnself.get_output(0)
@property
defstderr(self):
returnself.get_output(1)
@property
defstatus(self):
returnself.pipe.returncode
defget_output(self,index):
return"".join(self.streams[index][1])
defon_finish(self):
raiseNotImplemented()
classSubprocess(GenericSubprocess):
"""Createnewinstance
Arguments:
callback:methodtobecalledaftercompletion.Thismethodshouldtake3arguments:statuscode(int),stdout(str),stderr(str),has_timed_out(boolean)
timeout:walltimeallocatedfortheprocesstocomplete.AfterthisexpiresTask.canceliscalled.Anegativetimeoutvaluemeansnolimitisset
Thetaskisnotstarteduntilstartiscalled.Theprocesswillthenbespawnedusingsubprocess.Popen(**popen_args).Thestdoutandstderrarealwayssettosubprocess.PIPE.
"""
def__init__(self,callback,*args,**kwargs):
"""Createnewinstance
Arguments:
callback:methodtobecalledaftercompletion.Thismethodshouldtake3arguments:statuscode(int),stdout(str),stderr(str),has_timed_out(boolean)
timeout:walltimeallocatedfortheprocesstocomplete.AfterthisexpiresTask.canceliscalled.Anegativetimeoutvaluemeansnolimitisset
Thetaskisnotstarteduntilstartiscalled.Theprocesswillthenbespawnedusingsubprocess.Popen(**popen_args).Thestdoutandstderrarealwayssettosubprocess.PIPE.
"""
self.callback=callback
self.done_callback=False
GenericSubprocess.__init__(self,*args,**kwargs)
defon_finish(self):
ifnotself.done_callback:
self.done_callback=True
preventcallingcallbacktwice
self.ioloop.add_callback(functools.partial(self.callback,self.status,self.stdout,self.stderr,self.has_timed_out))
if__name__=="__main__":
ioloop=tornado.ioloop.IOLoop.instance()
defprint_timeout(status,stdout,stderr,has_timed_out):
assert(status!=0)
assert(has_timed_out)
print"OKstatus:",repr(status),"stdout:",repr(stdout),"stderr:",repr(stderr),"timeout:",repr(has_timed_out)
defprint_ok(status,stdout,stderr,has_timed_out):
assert(status==0)
assert(nothas_timed_out)
print"OKstatus:",repr(status),"stdout:",repr(stdout),"stderr:",repr(stderr),"timeout:",repr(has_timed_out)
defprint_error(status,stdout,stderr,has_timed_out):
assert(status!=0)
assert(nothas_timed_out)
print"OKstatus:",repr(status),"stdout:",repr(stdout),"stderr:",repr(stderr),"timeout:",repr(has_timed_out)
defstop_test():
ioloop.stop()
t1=Subprocess(print_timeout,timeout=3,args=["sleep","5"])
t2=Subprocess(print_ok,timeout=3,args=["sleep","1"])
t3=Subprocess(print_ok,timeout=3,args=["sleepdsdasdas","1"])
t4=Subprocess(print_error,timeout=3,args=["cat","/etc/sdfsdfsdfsdfsdfsdfsdf"])
t1.start()
t2.start()
try:
t3.start()
assert(false)
except:
print"OK"
t4.start()
ioloop.add_timeout(time.time()+10,stop_test)
ioloop.start()






人人能够先用uwsgi,要仍是有压力和梗塞的话,能够用用nginx做负载。
我本人的履历来看仍是这个靠谱~

本文出自“峰云,就她了。”博客,请务必保存此出处http://rfyiamcool.blog.51cto.com/1030776/1227629


欢迎大家来到仓酷云论坛!
作者: 兰色精灵    时间: 2015-1-16 19:06
标题: 带来一篇多套计划来进步python web框架的并发处置才能
Windows有MS-DOS?方式,在该方式下通过输入DOS命令来操作电脑;Linux与Windows类似,也有命令方式,Linux?启动后如果不执行?X-WINDOWS,就会处于命令方式下,必须发命令才能操作电脑。?
作者: 灵魂腐蚀    时间: 2015-1-25 16:16
清楚了解网络的基础知识,特别是在Linux下应用知识,如接入internet等等。
作者: 分手快乐    时间: 2015-2-3 12:09
随着Linux应用的扩展,出现了不少Linux社区。有一些非常优秀的社区往往是Linux高手的舞台,如果在探讨高级技巧的论坛张贴非常初级的问题经常会没有结果。
作者: 爱飞    时间: 2015-2-9 01:30
对于英语不是很好的读者红旗 Linux、中标Linux这些中文版本比较适合。现在一些Linux网站有一些Linux版本的免费下载,这里要说的是并不适合Linux初学者。
作者: 小妖女    时间: 2015-2-26 18:31
Linux最大的特点就是其开源性,这一点是十分难得的,这也是它能够存在到现在的原因之一。
作者: 海妖    时间: 2015-3-8 17:35
首先Linux是开源的,这也是最主要的原因,想学windows,Unix,对不起我们没源代码。也正是因为这样,Linux才能够像滚雪球一样越滚越大,发展到现在这种规模。
作者: 透明    时间: 2015-3-16 15:48
掌握硬件配置,如显卡,声卡,网卡等,硬件只要不是太老或太新一般都能被支持,作为一名Linux系统管理员建议多阅读有关硬件配置文章,对各种不支持或支持不太好的硬件有深刻的了解。
作者: 深爱那片海    时间: 2015-3-23 00:07
最好先搜寻一下论坛是否有您需要的文章。这样可以获得事半功倍的效果。




欢迎光临 仓酷云 (http://ckuyun.com/) Powered by Discuz! X3.2