2009-10-13 88 views
2

對於我正在開發的應用程序,用戶使用多部分表單數據(content-type:multipart/form-data)提交gzip HTTP POST請求(內容編碼:GZIP)。我使用mod_deflate作爲輸入過濾器進行解壓縮,並通過mod_wsgi在Django中處理Web請求。響應gzip請求時Apache滯後

一般來說,一切都很好。但是對於某些請求(確定性的),從請求到響應有幾分鐘的延遲。調查顯示,django中的處理是立即完成的,但服務器的響應失速。如果請求不是GZIPed,則一切正常。

請注意,要處理mod_wsgi中的毛刺,我將content-length設置爲未壓縮的消息大小。

有沒有人遇到這個問題?有沒有辦法輕鬆調試Apache,因爲它處理響應?

回答

5

你認爲mod_wsgi存在哪些小故障?

事情的一個簡單事實是,WSGI 1.0不支持變更輸入過濾器,這會改變請求內容的內容長度。因此,從技術上講,在使用WSGI 1.0時,您無法在Apache中使用mod_deflate獲取請求內容。將內容長度設置爲除實際大小之外的值很可能會填滿mod_deflate的操作。

如果您希望能夠處理壓縮的請求內容,您需要跳出WSGI 1.0規範並使用非標準代碼。

我建議你有一個讀:

http://blog.dscpl.com.au/2009/10/details-on-wsgi-10-amendmentsclarificat.html

這就解釋了這個問題,它的建議。

我非常建議你把這個問題交給官方mod_wsgi mailing list討論你如何編寫你的代碼。但是,如果您正在使用某個Python框架,那麼您可能會限制您可以執行的操作,因爲它們將實施WSGI 1.0,而您無法執行此操作。


更新1

從mod_wsgi的名單上的討論,原來的WSGI應用程序應該被包裹在以下WSGI中間件。這隻適用於WSGI適配器,它實際上提供了一個空字符串作爲輸入的結束標記,這是WSGI 1.0不需要的。這應該只能用於小型上傳,因爲所有內容都被讀入內存。如果需要大的壓縮上傳,那麼累積時的數據應該被寫出到文件中。

class Wrapper(object): 

    def __init__(self, application): 
     self.__application = application 

    def __call__(self, environ, start_response): 
     if environ.get('HTTP_CONTENT_ENCODING', '') == 'gzip': 
      buffer = cStringIO.StringIO() 
      input = environ['wsgi.input'] 
      blksize = 8192 
      length = 0 

      data = input.read(blksize) 
      buffer.write(data) 
      length += len(data) 

      while data: 
       data = input.read(blksize) 
       buffer.write(data) 
       length += len(data) 

      buffer = cStringIO.StringIO(buffer.getvalue()) 

      environ['wsgi.input'] = buffer 
      environ['CONTENT_LENGTH'] = length 

     return self.__application(environ, start_response) 


application = Wrapper(original_wsgi_application_callable) 
+0

至於毛刺,實際上我們討論過這個以前在這裏: http://code.djangoproject.com/ticket/10819#comment:1 我把您的評論的意思,我應該只是設置內容長度爲未壓縮的消息大小。這樣做一直工作得很好,直到現在... 無論哪種方式,我問了mod_wsgi列表。謝謝你的幫助。 – UsAaR33 2009-10-14 01:16:40

+1

有關此的關於mod_wsgi列表的討論位於'http://groups.google.com/group/modwsgi/browse_frm/thread/54eba8ddff1a8eec'。 – 2009-10-14 04:46:16