2009-10-13 35 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