2009-06-19 75 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程序來執行您想要的操作。