2009-06-19 86 views
2

我拥有一个写成CGI的遗留Python应用程序。到目前为止,这工作正常,但并发用户的数量将在不久的将来大幅增加。 在这里我读到:“CGI适合低流量的网站,但它对于其他任何东西都有一些性能问题。我知道以另一种方式开始会更好,但CGI是现在的情况。Python cgi性能

有人可以指点我如何保持CGI的表现,而不必重写所有的代码?

回答

6

CGI不能缩放,因为每个请求都要求一个全新的服务器进程。这是很大的开销。 mod_wsgi通过分叉一个进程并将请求交给那个正在运行的进程来避免开销。

我们假设应用程序是最糟糕的一种cgi。

最坏的情况是它有这样的文件。

my_cgi.py

import cgi 
print "status: 200 OK" 
print "content-type: text/html" 
print 
print "<!doctype...>" 
print "<html>" 
etc. 

您可以尝试 “包装” 原来CGI文件,使其WSGI。

wsgi.py

import cStringIO 
def my_cgi(environ, start_response): 
    page = cStringIO.StringIO() 
    sys.stdout= page 
    os.environ.update(environ) 
    # you may have to do something like execfile("my_cgi.py", globals=environ) 
    execfile("my_cgi.py") 
    status = '200 OK' # HTTP Status 
    headers = [('Content-type', 'text/html')] # HTTP Headers 
    start_response(status, headers) 
    return page.getvalue() 

这第一步,重写你的CGI应用程序到一个适当的框架。这需要很少的工作,并且会使CGI更具可扩展性,因为您不会为每个请求启动全新的CGI过程。

第二步是创建一个Apache使用的mod_wsgi服务器,而不是所有的CGI脚本。此服务器必须(1)解析URL的,(2)调用各种功能,如my_cgi示例函数。每个函数都将execfile旧CGI脚本不分叉新过程。

请参阅werkzeug了解有用的库。

如果您的应用程序CGI脚本具有某些结构(函数,类等),您可以导入这些结构并做更多的事情,比上述更聪明。更好的方法是这样的。

wsgi.py

from my_cgi import this_func, that_func 
def my_cgi(environ, start_response): 

    result= this_func(some_args) 
    page_text= that_func(result, some_other_args) 

    status = '200 OK' # HTTP Status 
    headers = [('Content-type', 'text/html')] # HTTP Headers 
    start_response(status, headers) 
    return page_text 

这需要更多的工作,因为你必须要了解的遗留应用程序。但是,这有两个好处。

  1. 它使您的CGI具有更高的可扩展性,因为您没有为每个请求启动新的过程。

  2. 它允许您重新考虑您的应用程序,可能会将其更改为适当的框架。一旦你完成了这个任务,就不难做出下一个步骤,并且转向TurboGearsPylonsweb.py来构建一个非常简单的框架。

+0

感谢您的详细回复。我的应用程序是最糟糕的一种。 不得不改变调用gi.FieldStorage(),MySQLdb和使用os模块的事情吗? – user37986 2009-06-19 12:27:35

3

使用FastCGI。如果我正确理解FastCGI,那么可以通过编写一个位于Web服务器和旧代码之间的非常简单的Python程序来执行您想要的操作。