2

私が開発しているアプリケーションの場合、ユーザーは gzip された HTTP POST リクエスト (コンテンツ エンコーディング: GZIP) をマルチパート フォーム データ (コンテンツ タイプ: マルチパート/フォーム データ) と共に送信します。mod_deflate を入力フィルターとして使用して解凍し、Web リクエストは mod_wsgi を介して Django で処理されます。

一般的に、すべて問題ありません。ただし、特定の要求 (決定論的) では、要求から応答までにほぼ 1 分の遅延があります。調査の結果、django での処理はすぐに行われますが、サーバーからの応答が停止します。リクエストが GZIP されていない場合は、すべて正常に機能します。

mod_wsgi の不具合に対処するために、content-length を圧縮されていないメッセージ サイズに設定したことに注意してください。

誰かがこの問題に遭遇しましたか? 応答を処理するときにApacheを簡単にデバッグする方法はありますか?

4

1 に答える 1

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 メーリング リストに持ち込むことを強くお勧めします。ただし、Python フレームワークの 1 つを使用している場合でも、これを行うことができない WSGI 1.0 を実装するため、できることが制限される可能性があります。


更新 1

mod_wsgi リストに関する議論から、元の WSGI アプリケーションは次の WSGI ミドルウェアでラップする必要があります。これは、WSGI 1.0 が必要としない、入力用のエンド センティネルとして実際に空の文字列を提供する WSGI アダプタでのみ機能します。すべてがメモリに読み込まれるため、これはおそらく小さなアップロードにのみ使用する必要があります。大規模な圧縮アップロードが必要な場合は、蓄積されたデータを代わりにファイルに書き出す必要があります。

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)
于 2009-10-13T22:22:50.647 に答える