Apache отстает при ответе на сжатые запросы - PullRequest
2 голосов
/ 13 октября 2009

Для приложения, которое я разрабатываю, пользователь отправляет GZIP-запрос HTTP POST (content-encoding: GZIP) с данными многочастной формы (тип контента: multipart / form-data). Я использую mod_deflate в качестве входного фильтра для распаковки, и веб-запрос обрабатывается в Django через mod_wsgi.

В общем, все хорошо. Но для определенных запросов (детерминированных) от запроса к ответу наблюдается почти минутное отставание. Расследование показывает, что обработка в django выполняется немедленно, но ответ сервера останавливается. Если запрос не GZIPed, все работает хорошо.

Обратите внимание, что для устранения проблемы в mod_wsgi я установил для content-length размер несжатого сообщения.

Кто-нибудь сталкивался с этой проблемой? Есть ли способ легко отладить apache при обработке ответов?

1 Ответ

5 голосов
/ 14 октября 2009

Какой глюк, по вашему мнению, существует в mod_wsgi?

Простой факт в том, что WSGI 1.0 не поддерживает мутирующие входные фильтры, которые изменяют длину содержимого запроса. Таким образом, технически вы не можете использовать mod_deflate в Apache для запроса содержимого при использовании WSGI 1.0. Ваша установка длины содержимого в качестве значения, отличного от фактического размера, скорее всего приведет к заполнению операции mod_deflate.

Если вы хотите обрабатывать сжатый контент запроса, вам нужно выйти за пределы спецификации WSGI 1.0 и использовать нестандартный код.

Предлагаю прочитать:

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

Это объясняет эту проблему и предложения по ней.

Я бы очень предложил вам перенести этот вопрос в официальный список рассылки mod_wsgi для обсуждения того, как вам нужно написать свой код. Однако, если вы используете одну из платформ 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)
...