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% がかかります....