5

Herokuでdjango/gunicornサーバーを実行しています。私たちのユーザーのほとんどは、モバイル ネットワークがあまり良くない国に住んでいるため、接続が不安定になることがよくあります。

私たちのリクエストのほとんどはモバイル デバイスからの「生の投稿」であり、POST リクエストが完全に送信されていない場合でも、リクエストはすでに送信されており、ガンコーン ワーカーによって処理されているようです。ワーカーがリクエストを処理してデータを読み取ろうとすると、残りのデータを待ってハングアップします。この動作は「ストリーミング」モードでのファイル/画像データの読み取りには意味がありますが、私たちの場合は意味がありません。すべての投稿が比較的小さく、Web サーバー全体で簡単に読み取られてから、gunicorn に転送されるだけだからです。ワーカー。

このような早期のハンドオフは、このようなリクエストが並行して多数ある場合に問題を引き起こします。すべてのワーカーがブロックされる可能性があるためです。現在、worker/dyno の数を増やすことで問題を解決していますが、かなりコストがかかります。Webサーバーまたはgunicornのいずれかを強制的に待機させ、リクエストが完全に送信された後にのみワーカーに転送する方法を見つけることができませんでした.

クライアント側から完全に送信された (サーバーによって完全に受信された) 場合にのみ、heroku の Web サーバー/gunicorn が要求を gunicorn ワーカーに転送するようにする方法はありますか?

いくつかのサンプルコード (newrelic の「命令ごと」のトレースを追加して、これが問題を引き起こしている正確な行であることを確認しました):

def syncGameState(request):
    transaction = agent.current_transaction()
    with agent.FunctionTrace(transaction, "syncGameState_raw_post_data", 'Python/EndPoint'):
        data = request.raw_post_data
    with agent.FunctionTrace(transaction, "syncGameState_gameStateSyncRequest", 'Python/EndPoint'):
        sync_request = sync_pb2.gameStateSyncRequest()
    with agent.FunctionTrace(transaction, "syncGameState_ParseFromString", 'Python/EndPoint'):
        sync_request.ParseFromString(data)

以下は、この遅いリクエストの例に対する New Relic の測定値です (7K のデータを含む POST でした)。POST の読み取りには、メソッド時間の 99% がかかります....

ここに画像の説明を入力

4

2 に答える 2

0

ここでの本当の問題は、gunicornがブロックしていることだと私には思えます。これは、gunicorn(デフォルト)が同期ワーカーを使用してタスクを実行するためです。これは、Webリクエストがgunicornにヒットすると、応答が返されるまでブロックされることを意味します。この場合、長時間です。

この問題を回避するには、geventとgunicornを使用して非ブロッキングIOを実行します。ほとんどの時間はIOの処理に費やされているため、これにより、gunicornがより多くのWebリクエストを並行して処理できるようになります。

geventをgunicornで使用するには、gevent(pip install -U gevent)をインストールし、次を追加してgunicornの起動コマンドを変更する必要がありますgunicorn -k gevent(これにより、gunicornにgeventをワーカーとして使用するように指示されます)。

于 2012-09-18T05:43:35.393 に答える
0

この記事を読んで、Waitres などのリクエスト バッファリング HTTP サーバーを調査することをお勧めします。

于 2015-03-16T20:16:36.300 に答える