`
gashero
  • 浏览: 962837 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

修复flup中threadpool在twisted中运行

阅读更多

 

修复flup中threadpool在twisted中运行的日记

作者: 日期:
gashero
2009-09-04

1   简介

希望在twistd托管模式中运行flup的FastCGI服务器,但是启动以后一直有可以接受连接,但是不接受请求的问题。本文记录修复该问题的过程以及方法。

2   故障描述

twistd托管daemon中的flup可以接受连接,但是不接受请求。

3   调试流程

3.1   flup的源码安装

默认使用egg打包方式放在标准Python模块目录,安装后的看不到源码。所以删除了已经安装的flup,而将解压后的flup源码目录拷贝到Python模块目录了。方便进一步调试。

3.2   确定导入的flup模块范围

只有先确定了导入模块的范围才能更好的定位问题点。而Python的 sys.modules 字典对象展示了所有导入对象。

如下两句在阻塞启动flup服务器之前提供打印所有导入模块的功能:

print 'modules',sys.modules.keys()
print 'flup mod',filter(lambda x:'flup' in x,sys.modules.keys())

如此打印出来的模块还是有诸多干扰,整理一下发现如下flup的模块被导入了:

flup
flup.server
flup.server.flup
flup.server.fcgi
flup.server.fcgi_base
flup.server.threadpool
flup.server.threadedserver

再排除了 flup.server.flup 和顶级没用模块以后目标定位在4个模块中:

flup.server.fcgi
flup.server.fcgi_base
flup.server.threadpool
flup.server.threadedserver

好吧,噩梦来了,以前开发的CDN系统就曾经发现过在twistd的daemon模式中使用threadpool无法启动线程的问题。恐怕这次的主要问题点也在这里。这4个模块总代码量为1635行,还好,还不至于很抓狂。

4   FastCGI服务器启动跟踪

4.1   外部入口

from flup.server import fcgi
server=fcgi.WSGIServer(wsgifunc,bindAddress=('0.0.0.0',8080))
server.run()

4.2   flup.server.fcgi 中的初始化

from flup.server.fcgi_base import BaseFCGIServer,FCGI_RESONDER
from flup.server.threadedserver import ThreadedServer

其中 WSGIServer 继承自 fcgi_base.BaseFCGIServerflup.server.threadedserver.ThreadServer 。其 __init__() 构造函数调用了两个父类的构造函数, BaseFCGIServer 的在前。

4.3   server.run() 流程

调用了 flup.server.fcgi.WSGIServer.run() 函数,其定义中的阻塞部分在:

sock=self._setupSocket()
ret=ThreadedServer.run(self,sock)   #这句阻塞
self._cleanupSocket(sock)
return ret

4.4   threadedserver 模块分析

该模块用于处理多线程服务器的线程部分,而不管FastCGI的处理。也是唯一一处调用了 threadpool 模块的地方。共计175行。

这里对threadpool模块的引用只有3处:

  1. 45行,导入模块:

    from flup.server.threadpool import ThreadPool
    
  2. 54行,初始化时,定义为服务器的线程池对象:

    self._threadPool=ThreadPool(**kw)
    
  3. 97行,生成任务,添加任务到线程池:

    conn=self._jobClass(clientSock,addr,*self._jobArgs)
    if not self._threadPool.addJob(conn,allowQueuing=False):
        clientSock.close()
    

由最后一处调用可见不是几年前郁闷我的那个threadpool模块了,不过相信问题是一样的,就是twistd托管daemon模式时,线程的运行是有问题的。

4.5   fcgi_base 中对thread和threading模块的引用分析

大部分地方是使用了线程锁。而使用了启动线程的地方有一处,MultiplexedConnection类的865行,启动线程:

def _start_request(self,req):
    thread.start_new_thread(req.run,())

实际调试发现如上代码的启动中根本没有创建该类的对象,所以可以排除这里出问题的可能。

至于其他地方使用的锁,就先假设不会出问题吧。

4.6   threadpool 结构分析

该模块一共121行,是flup的作者自己写的,其中只有一个类 ThreadPool ,其包含3个方法:

class ThreadPool(object):
    def __init__(self,minSpare=1,maxSpare=5,maxThreads=sys.maxint)
    def addJob(self,job,allQueuing=True)
    def _worker(self)

虽然引用了thread和threading两个模块,不过任务都比较明晰。启动线程使用 thread.start_new_thread(self._worker,()) ,而threading模块仅用于定义锁 self._lock=threading.Condition()

5   修改尝试

5.1   修改threadpool模块中线程启动方式

以前是使用 thread.start_new_thread 方式启动,尝试修改成threading模块的线程对象方式,以及其守护线程模式:

thrd=threading.Thread(target=self._worker)
thrd.setDaemon(True)
thrd.start()

尝试失败。启动的线程仍然在twistd托管时消失了。

5.2   修改threadpool的实现,改为twisted的线程

使用twisted的线程池的相同接口ThreadPool实现:

class ThreadPool(object):
    """Twisted ThreadPool warpper"""

    def __init__(self,minSpare=1,maxSpare=5,maxThreads=sys.maxint):
        #reactor.suggestThreadPoolSize(maxSpare)
        return

    def addJob(self,job,allowQueuing=True):
        print 'call addjob',repr(job)
        reactor.callInThread(job.run)
        return
#threadpool.ThreadPool=ThreadPool
threadedserver.ThreadPool=ThreadPool

重新尝试启动,因为没有阻塞调用 reactor.run() 的地方,所以线程启动失败。

5.3   修改 threadedserver.ThreadedServer.run ,使得加入reactor的启动

这个主要就是利用twisted的思想,将整个函数切块,涉及到信号操作的部分使用 reactor.callFromThread() 调用,其他部分则使用 reactor.callInThread() 放在线程里执行就可以了。

我为了避免污染flup在site-packages目录中的代码,所以是自己在模块里面写代码,然后导入flup以后替换相关对象的方式实现的。这时将原来函数的代码复制过来,做修改,然后替换。同时需要另外导入一些模块,导入与替换:

import select
import errno
from flup.server.threadedserver import setCloseOnExec
threadedserver.ThreadedServer.run=threadedserver_run

通过这样改造以后 server.run() 就可以由twisted的线程进行托管了。启动代码如下:

server=fcgi.WSGIServer(wsgifunc,bindAddress=(addr,port))
reactor.callInThread(server.run)
application=service.Application('httprpc',uid=uid,gid=gid)

6   总结

通过如上一番对flup的改造,就可以将其运行在twisted托管模式了。由twistd负责捕捉错误输出、打印输出,并且使其运行在daemon模式。很方便。

这样修改以后还存在一点不足,就是在普通运行模式下也要用 reactor.callInThread(server.run) 来运行。这种情况下就没法使用Ctrl+C来终止程序了。而必须使用kill -9才行。

1
0
分享到:
评论

相关推荐

    python flup

    Python中的FLUP库是一个用于实现WSGI(Web服务器网关接口)协议的模块,特别适合在处理WebSocket协议和FastCGI协议时与像Nginx这样的HTTP服务器配合使用。FLUP提供了一个简单而高效的框架,使得Python应用程序能够...

    flup安装包

    在Web开发中,FastCGI是一种让交互式应用程序持久运行并高效处理请求的技术。它不同于传统的CGI(通用网关接口),因为CGI每次处理请求时都会启动新的进程,而FastCGI则保持进程常驻,从而提高了性能。 Flup是...

    web.py flup

    总结来说,web.py提供了一个轻量级的Web开发框架,而flup则帮助你在服务器上以FastCGI方式运行web.py应用,提升性能和可扩展性。通过合理利用这两个工具,你可以构建高效、易于维护的Python Web应用。

    flup3-master包

    "flup3-master"包可能包含了Flup的源代码、示例应用或者其他辅助工具,用于帮助开发者在Windows环境中快速设置这个复杂的环境。通过理解和掌握这些组件的工作原理以及它们之间的协作,你就能在Windows系统上构建出一...

    flup-1.0.1

    安装完成后,Flup库可以在Python代码中导入并使用,以创建FastCGI服务器。例如,如果你有一个名为`app.py`的简单Web应用,你可以使用Flup将它包装成FastCGI服务: ```python from flup.server.fcgi_wsgi import ...

    distribute-0.7.3,flup3-master

    python3下运行django1,6不能运行提示需要安装flup,但是flup1.02不能安装在python3下的,需要安装flup3-master,安装flup3-master需要先安装distribute-0.7.3

    flup-py3-master

    总结来说,“flup-py3-master”项目是一个为Python 3编写的Flup库的分支,旨在帮助开发者在Nginx环境中利用FastCGI协议部署和运行Python Web应用。这个项目可能包含了源代码、测试、文档和安装脚本,便于用户理解和...

    flup-1.0.1.tar

    python kuangjia cai fast

    flup-1.0.2

    flup: random Python WSGI stuff This Python package is a random collection of WSGI modules I've written. fcgi and publisher have long existed since I became interested in Python web programming a few ...

    Python库 | flup-1.0.3.dev_20110111-py2.7.egg

    资源分类:Python库 所属语言:Python 资源全名:flup-1.0.3.dev_20110111-py2.7.egg 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    flup:节点js中基于终端的TCP聊天服务器和客户端

    Flup是生活在终端中的一个简单的聊天应用程序。 它同时实现了server和client 。 创建该项目是为了学习node.js套接字和net模块。 用法: Usage: index [options] Options: -h, --help output usage information -...

    Windows系统下使用flup搭建Nginx和Python环境的方法

    与Linux下不同的是,nginx在windows下是以一个应用程序的方式运行,而不是以一个服务运行(难怪没人在windows服务器上用nginx) 把刚刚下载好的两个压缩包都解压到C:\nginx\, C:\flup\(目录可自己

    Page Flup-crx插件

    Page Flup的鼠标手势操作理念源自于许多高级用户的习惯,这种操作方式在许多其他软件和应用中也有所体现,如浏览器中的其他扩展、游戏控制、图形编辑软件等。通过鼠标手势,用户可以更直观、快捷地执行预定义的动作...

    Flup页面「Page Flup」-crx插件

    用鼠标翻页 这个小扩展可以让你节省宝贵的时间。只需安装它,打开您最喜爱的网站,将鼠标移动到左侧,直到停止并点击 - 页面将被抬起。 支持语言:English,русский

    Fastcgi 中文参考手册(DOC).rar

    在本书中,读者将学习如何配置Web服务器以支持FastCGI,理解FastCGI的配置选项,以及如何优化FastCGI进程管理以提升服务器性能。此外,还会涵盖如何调试FastCGI应用,解决可能出现的问题,以及与其他Web技术(如SSL/...

    在Mac OS上部署Nginx和FastCGI以及Flask框架的教程

    本教程主要集中在使用Nginx作为Web服务器,利用FastCGI协议与应用服务器Flup进行通信,并运行基于Python的Flask框架。 2. Flask框架特点: Flask是一个使用Python编写的轻量级Web框架,旨在保持核心简单而易于扩展...

    在Windows系统上搭建Nginx+Python+MySQL环境的教程

    运行nginx.exe后本地打开http://localhost,将会看到欢迎页面,这证明nginx在本地运行良好,如果没有出现欢迎页面,请检查是否有进程占用了80端口。 2 安装flup 下载对应版本的flup,这里下载flup3.x版本,适合...

    fastcgi中文手册.pdf

    这些进程在Web服务器启动时创建,并持续运行,处理来自Web服务器的请求。 - **通信方式**:FastCGI进程通过套接字与Web服务器进行通信,可以是Unix域套接字或TCP/IP套接字,数据以二进制流的形式传输。 - **请求与...

Global site tag (gtag.js) - Google Analytics