Apache在响应gzip压缩请求时滞后

时间:2009-10-13 10:36:34

标签: django apache gzip mod-wsgi mod-deflate

对于我正在开发的应用程序,用户使用多部分表单数据(内容类型:multipart / form-data)提交gzip压缩HTTP POST请求(内容编码:GZIP)。我使用mod_deflate作为输入过滤器进行解压缩,并通过mod_wsgi在Django中处理Web请求。

一般来说,一切都很好。但对于某些请求(确定性的),从请求到响应几乎有一分钟的延迟。调查显示django中的处理是立即完成的,但是来自服务器的响应停止。如果请求不是GZIPed,则一切正常。

请注意,为了处理mod_wsgi中的毛刺,我将content-length设置为未压缩的消息大小。

有没有人遇到这个问题?有没有办法在处理响应时轻松调试apache?

1 个答案:

答案 0 :(得分: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)