[原创] flup源码-运行模型剖释 - python的fastcgi
2010-12-14 16:50
519 查看
flup作为python的fastcgi实现,可以独立作为一个WSGI的服务,或与django结合,使用django模版、ORM进行开发。django利用其多线程或多进程的运行模型!
flup官网:http://trac.saddi.com/flup
最终版本:1.0.3,官网最下面的publisher
与Middleware
都被去掉了,只剩下server,clent
文档: 没有,官方说源码就是最好的文档。
先看看django启动为fastcgi模式参数
:
这主要解释下flup运行模型: 线程(thread) 或 进程(prefork只支持lunix)
线程模型 method=threaded
1)线程池:flup.threadpool.py文件:
这里节选两个函数, 初始化时线程池把空闲线程维持在 minSpare与maxSpare之间,最大线程数 上限为maxThreads,这里看下django启动参数一致.
这线程池好东西阿,装flup库,写其它python多线程或异步的程序也可以引入使用,只要实现自己的MyJob类,直接调用addJob即可:
因为python本身并非真正的多线程,这个线程模并不是我程序最终选择的,尽管测试中发现它非常高效,省去了线程的创建、销毁。另外,另一个组在使用线程模型时,出现不稳定,运行久了时不时500。
线程模型可以直接使用kill -HUP 主进程PID进行安全退出,其使用 线程的join等待进程退出。 -TERM也行,-9你就悲剧了!
进程模型 method=prefork
进程要来得复杂,但最终运行时,稳定一些!内存与CPU都能用尽。
主要看flup.prefrokserver.py文件 PreforkServer 类。其使用linux的标准fork函数进行多进程的派生,每个派生出来的子进程都变成了单线程。只能在运行时进程线程创建!fork特性详看:
http://www.opengroup.org/onlinepubs/000095399/functions/fork.html
想创建为多线程 + 多进程的 fastcgi,看我的另一文章。
贴一个退出函数,当我们向主进程PID发出kill -HUP PID时,PreforkServer类调用以下函数,向每一个子进程发送一个中断信号SIGINT=2, 再等待10秒,注册一个alrm。子进程必需注册SIGINT信号,不然python虚拟机
将调用默认的键盘中断,子进程如正在处理HTTP请求,会异常中断!你就等着事务数据出乱吧!
多进程下注册自己的中断处理函数:
父进程与子进程之间使用非阻塞的sock对进程通信
flup只处理了 kill -HUP, -TERM 退出信号; -QUIT, -9 都将直接杀死进程,不能安全退出。
flup官网:http://trac.saddi.com/flup
最终版本:1.0.3,官网最下面的publisher
与Middleware
都被去掉了,只剩下server,clent
文档: 没有,官方说源码就是最好的文档。
先看看django启动为fastcgi模式参数
:
manage.py runfcgi minspare=50 maxspare=200 maxchildren=1000 maxrequests=99999 host=127.0.0.1 port=8080 pidfile=./django.pid method=threaded # 解释下参数意义 # maxspare为初始化的进程/线程数,也是最少个数 # minspare为最少空闲进程/线程数, 注意空闲二字 # maxchildren 进程/线程上限,以每个py进程20~30M算,自己算下服务器内存能创建最大进程数吧! # maxrequests 处理多少个请求后,销毁进/线程,防内存泄漏,默认不销毁 # method = prefork|threaded 进程或线程跑你的程序,默认进程。 # 其它几个不解释
这主要解释下flup运行模型: 线程(thread) 或 进程(prefork只支持lunix)
线程模型 method=threaded
1)线程池:flup.threadpool.py文件:
class ThreadPool(object): """ Thread pool that maintains the number of idle threads between minSpare and maxSpare inclusive. By default, there is no limit on the number of threads that can be started, but this can be controlled by maxThreads. """ def __init__(self, minSpare=1, maxSpare=5, maxThreads=sys.maxint): self._minSpare = minSpare self._maxSpare = maxSpare self._maxThreads = max(minSpare, maxThreads) self._lock = threading.Condition() self._workQueue = [] self._idleCount = self._workerCount = maxSpare self._threads = [] self._stop = False # Start the minimum number of worker threads. for i in range(maxSpare): self._start_new_thread()
这里节选两个函数, 初始化时线程池把空闲线程维持在 minSpare与maxSpare之间,最大线程数 上限为maxThreads,这里看下django启动参数一致.
这线程池好东西阿,装flup库,写其它python多线程或异步的程序也可以引入使用,只要实现自己的MyJob类,直接调用addJob即可:
from flup.server.threadpool import ThreadPool gThreadPool = ThreadPool() class MyJob(object): def __init__(self, func,args): self._func = func self._args = copy.deepcopy(args) def run(self): try: return self._func(**self._args) except Exception, e: print e if __debug__:raise e def fun(e): print e gThreadPool.addJob(MyJob(fun, {'e':'test'}))
因为python本身并非真正的多线程,这个线程模并不是我程序最终选择的,尽管测试中发现它非常高效,省去了线程的创建、销毁。另外,另一个组在使用线程模型时,出现不稳定,运行久了时不时500。
线程模型可以直接使用kill -HUP 主进程PID进行安全退出,其使用 线程的join等待进程退出。 -TERM也行,-9你就悲剧了!
进程模型 method=prefork
进程要来得复杂,但最终运行时,稳定一些!内存与CPU都能用尽。
主要看flup.prefrokserver.py文件 PreforkServer 类。其使用linux的标准fork函数进行多进程的派生,每个派生出来的子进程都变成了单线程。只能在运行时进程线程创建!fork特性详看:
http://www.opengroup.org/onlinepubs/000095399/functions/fork.html
想创建为多线程 + 多进程的 fastcgi,看我的另一文章。
贴一个退出函数,当我们向主进程PID发出kill -HUP PID时,PreforkServer类调用以下函数,向每一个子进程发送一个中断信号SIGINT=2, 再等待10秒,注册一个alrm。子进程必需注册SIGINT信号,不然python虚拟机
将调用默认的键盘中断,子进程如正在处理HTTP请求,会异常中断!你就等着事务数据出乱吧!
def _cleanupChildren(self): """ Closes all child sockets (letting those that are available know that it's time to exit). Sends SIGINT to those that are currently processing (and hopes that it finishses ASAP). Any children remaining after 10 seconds is SIGKILLed. """ # Let all children know it's time to go. for pid,d in self._children.items(): if d['file'] is not None: d['file'].close() d['file'] = None if not d['avail']: # Child is unavailable. SIGINT it. try: os.kill(pid, signal.SIGINT) except OSError, e: if e[0] != errno.ESRCH: raise def alrmHandler(signum, frame): pass # Set up alarm to wake us up after 10 seconds. oldSIGALRM = signal.getsignal(signal.SIGALRM) signal.signal(signal.SIGALRM, alrmHandler) signal.alarm(10)
多进程下注册自己的中断处理函数:
import signal def _intHandler(signum, frame): # 你可以不做任何事,只是不让python虚拟机调用默认键盘中断 pass #这个_int变量属于子进程级的,不同的子进程不一样 _int = None # 你也可以不要这个变量,多次去调用signal.signal(signal.SIGINT, _intHandler) def index(request): global _int if _int is None: signal.signal(signal.SIGINT, _intHandler) # 以下处理你的HTTP请求
父进程与子进程之间使用非阻塞的sock对进程通信
def _spawnChild(self, sock): """ Spawn a single child. Returns True if successful, False otherwise. """ # This socket pair is used for very simple communication between # the parent and its children. parent, child = socket.socketpair() parent.setblocking(0) setCloseOnExec(parent) child.setblocking(0) setCloseOnExec(child) # 接着fork,然后调用 self._chlid进入子进程。 以下去除了容错代码 pid = os.fork() if not pid: # Child pid = os.getpid() os.setpgid(pid, pid) try: # Enter main loop. self._child(sock, parent) except KeyboardInterrupt: pass sys.exit(0) # mail loop结束后,子进程退出 else: # Parent pass def _child(self, sock, parent): """Main loop for children.""" while True: # Wait for any activity on the main socket or parent socket. r, w, e = select.select([sock, parent], [], []) # 子进程一个while True的循环处理请求,并使用select模型等待主进程或主端口发来的请求。
flup只处理了 kill -HUP, -TERM 退出信号; -QUIT, -9 都将直接杀死进程,不能安全退出。
相关文章推荐
- 在windows下运行Felzenszwalb的Deformable Part Model(DPM)源码voc-release3.1来训练自己的模型
- 转:windows下安装设置Nginx+python+flup+django,并设为服务运行!
- 原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)
- windows配置openerp 7.0源码运行环境(eclipse4.2 + pydev + python2.7)
- nginx+python+fastcgi环境配置(flup版本)
- 原创:用python把链接指向的网页直接生成图片的http服务及网站(含源码及思想)
- 教女朋友学Python(一)运行环境搭建[原创]_python_脚本之家
- 基于隐语义模型的推荐算法---《推荐系统实践》---Python源码(11)
- Cherokee HTTP Server源码分析(一) – cherokee运行模型
- Spark源码分析之二:Job的调度模型与运行反馈
- [原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程
- python+fastcgi+flup获取请求的数据和环境变量
- Python Web初学解惑之 WSGI、flup、fastcgi、web.py的关系
- 【原创】分享一个Python爬虫源码|爬虫批量爬取图片
- windows下安装设置Nginx+python+flup+django,并设为服务运行!
- 原创新闻 加速Python运行的工具
- WINDOWS操作系统下OpenERP源码运行的环境:eclipse + pydev + python2.7
- 完美原创:centos7.1 从源码升级安装Python3.5.2
- Python IDLE 运行错误:IDLE's subprocess didn't make connection. --已解决(原创)!
- [有码有真相]python unittest2 源码解读及各类运行测试方法示例