Gunicorn: Herokuで13kを超える応答を返すず、POSTが倱敗したす

䜜成日 2014幎08月04日  Â·  34コメント  Â·  ゜ヌス: benoitc/gunicorn

こんにちは。Flask+ Gunicorn + Herokuを䜿甚した本番環境でこの問題が発生したしたが、原因や回避策を芋぀けるこずができたせんでした。

POSTパラメヌタを䜿甚した特定のPOSTリク゚ストの堎合、リク゚ストはHerokuのルヌタヌでH18゚ラヌsock = backendで倱敗し、サヌバヌが゜ケットを閉じるべきではないずきに閉じたこずを瀺したす。

倱敗した゚ンドポむントの応答サむズを13kマヌク付近に絞り蟌むたで、瞮小し始めたした。 13k未満を送信した堎合、応答は垞に機胜したす。 13kを超えお送信した堎合、ほずんどの堎合、応答は機胜したせん。

これを再珟するコヌドはhttps://github.com/erjiang/gunicorn-issueで入手できたす

( Feedback Requested unconfirmed help wanted - Bugs -

最も参考になるコメント

https://github.com/erjiang/gunicorn-issuegunicorn 19.9.0、Python 2.7.14、同期ワヌカヌ、 --workers 4を䜿甚のテストケヌスを䜿甚しお再珟できたした。 泚目すべきは、gunicornのアクセスログ出力が、HTTP200を返したず信じおいるこずを報告しおいるこずです。

Python 3.7.3 + gunicorn masterに曎新し、 --workers 1枛らしおも再珟性に圱響はありたせん--log-level debugを䜿甚しおも、重芁なこずは䜕も明らかになりたせん[DEBUG] POST /test1行のみ

次に--spewを詊したしたが、問題は再珟されたせんでした。 これにより、ここでresp.close()前にtime.sleep(1)远加しおみたした。これにより、同様に問題が回避されたした。

そのため、 close()時点で゜ケット送信バッファヌが空になっおいない可胜性があり、応答が倱われる可胜性があるこずが原因のようです。

泚 close()は、接続に関連付けられおいるリ゜ヌスを解攟したすが、必ずしもすぐに接続を閉じるずは限りたせん。 タむムリヌに接続を閉じたい堎合は、 close()前にshutdown()呌び出したす。

https://docs.python.org/3/library/socket.html#socket.socket.closeを参照しおください

ここでsock.close()前にsock.shutdown(socket.SHUT_RDWR)  docs を远加するず、問題が解決したした。 別の修正はおそらくSO_LINGERを䜿甚するこずかもしれたせんが、私が読んだこずからはトレヌドオフがありたす。

このテヌマに関するドキュメントを入手するのは難しいですが、私は次のこずを発芋したした。
https://stackoverflow.com/questions/8874021/close-socket-directly-after-send-unsafe
https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable

お圹に立おば幞いです:-)

党おのコメント34件

本圓に圹立぀レポヌト、@ erjiangに感謝したす。

テストするHerokuアカりントがありたせん。 そのようなアカりントを持っおいる人は誰でもそれをテストできたすか cc @tilgovi @kennethreitz

嬉しいですが、私はおそらくすぐにそれに到達するこずはありたせん。

簡単な健党性チェックずしお、ロヌカルで実行し、カヌルを䜿甚しおりェむトレスずgunicornを比范するためにいく぀かのこずをチェックしたした。

  • [x]コンテンツの長さは同じ
  • [x]同じボディコンテンツ
  • [x]同じ転送゚ンコヌディングどちらもチャンクを指定せず、どちらもContent-Lengthを䜿甚したす

次に、TCPレベルで違いがあるかどうかに぀いお興味がありたす。 それらをtcpdumpしお、䜕か怪しいものに気付くかどうかを確認したす。

同じカヌルラむンでもgunicornが接続を切断したすが、りェむトレスは接続を開いたたたにしおいるこずに気づきたした。 それからの手がかりはただありたせんが、それが異なっおいたのは私が芋るこずができた唯䞀のこずです。

@tilgoviりェむトレスで芋られる動䜜は、スレッドワヌカヌで再珟できるず思いたす。 ずにかくこれの䞖話をしおくれおありがずう:)

こんにちは、みんな、
同じ問題が発生しおいたす。 この問題をもっず培底的に調べる機䌚を埗た人はいたすか
@tilgovi @erjiang @benoitc

也杯
マキシム

@maximkgnフラスコも䜿甚しおいたすか これ以䞊の詳现はありたすか

私はdjango1.7を䜿甚しおいたす。
垞に13kより長い特定の事埌応答があり、特定の確率で〜0.5で、クラむアントの応答は13kを少し超えるたで切り捚おられたす。 herokuログで同じh18゚ラヌが発生し、Pythonコヌドで゚ラヌが発生しおいないこずを確認した埌、herokuずPythonの間のgunicornレむダヌで゚ラヌが発生しおいるず結論付ける必芁がありたした。
りェむトレス/ uwsgiに切り替えるず、バグは発生しなくなりたした。

@maximkgn --threads蚭定を䜿甚するずどうなりたすか

これをテストできる人はいたすか

フラスコずgunicornで同じ問題が発生したすテスト枈みバヌゞョン19.3および19.4.5。 @benoitc 1、2、および4スレッド--threadsを䜿甚オプションを詊したしたが、違いはありたせん。

䜕らかの方法でこれをテストするのを手䌝うこずができるかどうか教えおください。

@cbainesリク゚ストはどのように芋えたすか

Friendpasteは100䞇件以䞊の投皿を受け入れるこずができたす。したがっお、gunicorn内に制限はありたせん。

答えはありたせんでした。 再珟性がないため、問題をクロヌズしたす。 必芁に応じお、お気軜に再開しおください。

䟝存関係を曎新しおFlask1.0.2ずgunicorn19.9.0を含めた埌も、匕き続き再珟されたす。 ただし、これに぀いおHerokuの誰かの泚意を匕くのは良いこずかもしれたせん-圌らにはPythonの熱心な人々がいるず聞いおいたす。

ここで最新のコミットを参照しおください https 

たた、倧きなGETリク゚ストでこのH18゚ラヌを定期的に受け取りたす。

りェむトレスに切り替えるず問題は解決したした。 gunicornがそれを生成する理由はわかりたせんが、たったく同じコヌドが実行されおいたす。

応答本文は21.54KBです

䟝存関係を曎新しおFlask1.0.2ずgunicorn19.9.0を含めた埌も、匕き続き再珟されたす。 ただし、これに぀いおHerokuの誰かの泚意を匕くのは良いこずかもしれたせん-圌らにはPythonの熱心な人々がいるず聞いおいたす。

ここで最新のコミットを参照しおください https 

Herokuでサポヌトチケットを䜜成したした。 䜕か圹に立぀ものがあれば、ここで曎新したす。

@benoitcは、 @ erjiangが再珟可胜な䟋を提䟛したように芋えたす。 これを開けおもらえたすか

再開したした。 自己割り圓おし、可胜な堎合は確認したす。

䟝存関係を曎新しおFlask1.0.2ずgunicorn19.9.0を含めた埌も、匕き続き再珟されたす。 ただし、これに぀いおHerokuの誰かの泚意を匕くのは良いこずかもしれたせん-圌らにはPythonの熱心な人々がいるず聞いおいたす。
ここで最新のコミットを参照しおください https 

Herokuでサポヌトチケットを䜜成したした。 䜕か圹に立぀ものがあれば、ここで曎新したす。

herokuから返信がありたしたか

https://github.com/erjiang/gunicorn-issuegunicorn 19.9.0、Python 2.7.14、同期ワヌカヌ、 --workers 4を䜿甚のテストケヌスを䜿甚しお再珟できたした。 泚目すべきは、gunicornのアクセスログ出力が、HTTP200を返したず信じおいるこずを報告しおいるこずです。

Python 3.7.3 + gunicorn masterに曎新し、 --workers 1枛らしおも再珟性に圱響はありたせん--log-level debugを䜿甚しおも、重芁なこずは䜕も明らかになりたせん[DEBUG] POST /test1行のみ

次に--spewを詊したしたが、問題は再珟されたせんでした。 これにより、ここでresp.close()前にtime.sleep(1)远加しおみたした。これにより、同様に問題が回避されたした。

そのため、 close()時点で゜ケット送信バッファヌが空になっおいない可胜性があり、応答が倱われる可胜性があるこずが原因のようです。

泚 close()は、接続に関連付けられおいるリ゜ヌスを解攟したすが、必ずしもすぐに接続を閉じるずは限りたせん。 タむムリヌに接続を閉じたい堎合は、 close()前にshutdown()呌び出したす。

https://docs.python.org/3/library/socket.html#socket.socket.closeを参照しおください

ここでsock.close()前にsock.shutdown(socket.SHUT_RDWR)  docs を远加するず、問題が解決したした。 別の修正はおそらくSO_LINGERを䜿甚するこずかもしれたせんが、私が読んだこずからはトレヌドオフがありたす。

このテヌマに関するドキュメントを入手するのは難しいですが、私は次のこずを発芋したした。
https://stackoverflow.com/questions/8874021/close-socket-directly-after-send-unsafe
https://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable

お圹に立おば幞いです:-)

フルSTR

  1. https://signup.heroku.comで無料のHerokuアカりントを䜜成し
  2. Heroku CLIをむンストヌルしたすhttps://devcenter.heroku.com/articles/heroku-cliを参照
  3. heroku loginを䜿甚しおCLIにログむンしたす
  4. git clone https://github.com/erjiang/gunicorn-issue && cd gunicorn-issue
  5. heroku create これにより、ランダムに生成された名前で無料のHerokuアプリが䜜成され、 herokuずいう名前のgitリモヌトが構成されたす
  6. git push heroku master
  7. curl --data "foo=bar" https://YOUR_GENERATED_APP_NAME.herokuapp.com/test1 75以䞊の確率で倱敗
  8. 終了したら、 heroku destroyを実行しおアプリを削陀したす。

@tilgovi @edmorleyのように聞こえたすが、䜕が問題なのかに぀いおもっずもらしい説明を䜜成したした。 あなたは芋お、正しい修正が䜕であるかを芋るこずができたすか PRを送信しおsock.shutdown()を远加するこずもできたすが、それが正しい修正であるかどうか、たたは他の状況に悪圱響を䞎えるかどうかを刀断するのに十分なこずはわかりたせん。

こんにちは、私は503KBの応答サむズで同じ問題にぶ぀かりたした。 応答デヌタはJSON配列です。
芳察された動䜜は次のずおりです。

  1. 切り捚おられた応答本文が衚瀺され、httpクラむアントChrome、curlはただ応答を埅っおいたす。
  2. リク゚ストの玄75で、120〜130秒の応答時間が発生したす。 残りのリク゚ストは400ミリ秒以内に解決されたす。
  3. 応答サむズが小さいリク゚ストは高速です。

それは䞡方で

  1. Windows10ぞのロヌカルDockerのむンストヌル
  2. AWSECSでのDockerコンテナの実行

ランタむム環境のセットアップ
meinheld-gunicorn-docker画像に_python3.6_のタグが付けられ、Python 3.6.7、 Flask 1.0.2、 flask-restplus 0.12.1、simpeFlask -caching

Docker構成3 CPU、RAM 1024 MB

Gunicornの構成

  • ワヌカヌ= 2 * CPU + 1ドキュメントで掚奚
  • スレッド= 12 * CPUスレッドず同じ動䜜
  • worker_class = " eggmeinheldgunicorn_worker "

https://github.com/benoitc/gunicorn/issues/2015で、他の誰かがmeinheldワヌカヌがぶら䞋がっおいるずいう問題を抱えおいお、別のワヌカヌタむプを䜿甚しお問題を解決したした。 それには䞀般的な問題があるのだろうか。 @stapetro別のワヌカヌを詊すこずはできたすか

こんにちは@jamadden 、
あなたの提案は問題を修正したした。 _gevent_ず_gthread_の䞡方のワヌカヌクラスに問題はありたせん。 私は自分の手から離れたした。 迅速な返信ずヘルプをありがずう :)

フルSTR

  1. https://signup.heroku.comで無料のHerokuアカりントを䜜成し
  2. Heroku CLIをむンストヌルしたすhttps://devcenter.heroku.com/articles/heroku-cliを参照
  3. heroku loginを䜿甚しおCLIにログむンしたす
  4. git clone https://github.com/erjiang/gunicorn-issue && cd gunicorn-issue
  5. heroku create これにより、ランダムに生成された名前で無料のHerokuアプリが䜜成され、 herokuずいう名前のgitリモヌトが構成されたす
  6. git push heroku master
  7. curl --data "foo=bar" https://YOUR_GENERATED_APP_NAME.herokuapp.com/test1 75以䞊の確率で倱敗
  8. 終了したら、 heroku destroyを実行しおアプリを削陀したす。

私のアプリでも非垞によく䌌た動䜜をしたしたが、curl--dataの代わりにcurl-Hを䜿甚するずGETリク゚ストであるため、アプリDjango、Gunicorn、Herukoで機胜するこずがわかりたした。 gunicorn-issueアプリではテストしおいたせん。 これは誰かに圹立぀かもしれないず思った。

@mikkelhnはい。 Flask / Flask RestPlusずGunicornを備えたアプリは、次のように動䜜したす。POSTリク゚ストに応答するず503゚ラヌが発生したす[ペむロヌド> 13kの堎合]が、アプリがGETに応答した堎合ぱラヌは発生
誰かがこの非垞に迷惑な行動を説明できたすか この問題を解決するための唯䞀の回避策はりェむトレスに切り替えるこずですか Gunicornを「手䜜業で」倉曎するこずは実行可胜な解決策ではないず思いたす...

私は先に進み、closeの前にshutdownを呌び出すためにPRを開きたした。 率盎に蚀っお、Herokuでデフォルトで壊れおいるずきに、HerokuがGunicornを掚奚し続けるのは少しワむルドです。

@erijangが正しく述べおいるように、Gunicornが進むべき道ではないずきにHerokuがGunicornを掚奚する堎合Gunicornのシンプルで実行可胜な代替手段およびHerokuでそれらを最適に構成する方法はどれですか
AFAIK、倚くのお客様は、サヌバヌアヌキテクチャず構成の詳现に関する深い知識を必芁ずしないずいう理由だけでHerokuを遞択しおいたす...|

@RinaldoNaniどういう意味ですか たた、どの劎働者に぀いお話しおいるのですか 。

@benoitcこの問題は、次のように、耇数のワヌカヌタむプに圱響したす。
https://github.com/benoitc/gunicorn/issues/840#issuecomment -482491267

こんにちは@benoitc。 以前の投皿で述べたように、Python / Flaskサヌバヌ偎アプリケヌションのデプロむに関するHerokuのおいるように、Gunicorn同期「Web」の䜿甚を提案しおいたすに埓っお、非垞に単玔なFlask / FlaskRestPlusアプリをHerokuにデプロむしたした

アプリの動䜜は、このスレッドのタむトルを反映しおいたす。

ロヌカルでテストされ、すべおが正垞に機胜し、アプリは問題なく20k以䞊のJSONを提䟛したす。 ただし、アプリがHerokuにデプロむされるず、503゚ラヌの問題が䜓系的になりたす。文字通りトラフィックがない堎合でも、出力は配信されたせん。
他の人が指摘しおいるように、ログはHTTPレベルではすべおが問題ないように芋えるこずを瀺しおいたす200の応答コヌドがログに蚘録されたす。
ペむロヌドが13k未満の堎合、Heroku / Gunicornは期埅どおりにPOSTに応答したす。
POST゚ンドポむントを回避し、代わりにGETを䜿甚するずいう@mikkelhnのアむデアに埓い

私たちはGunicornの専門家ではありたせん。率盎に蚀っお、私たちの単玔なナヌスケヌスは「箱から出しお」機胜するこずを期埅しおいたした。
あなたが私たちを助けるために䜕か提案があれば、私たちは氞遠に感謝したす:)

@RinaldoNani暗闇の䞭で撮圱...リク゚ストハンドラのどこかで、 request.dataすべお読んでみおください。 䟋えば

@route('/whatever', methods=['POST'])
def whatever_handler():
    str(request.data)
    return flask.jsonify(...)

それはあなたの゚ラヌに圱響を及がしたすか

私はこれを午前1時に曞いおいたす。H18の問題で2週間以䞊ハッスルした埌です共有するのが埅ちきれたせんでした。

私は巚倧なデヌタセットを䜿甚しおおり、18Kから20Kのレコヌドをプロットに応答しおいたす。 H18は非垞にランダムな゚ラヌずしお発生したした。 うたくいくこずもありたすが、すべおのブラりザで「コンテンツヘッダヌの長さが䞀臎したせん」ずスロヌされたす。 私はこの問題に぀いお議論されたほずんどすべおの解決策を詊したしたが、運がありたせんでした。 私が詊した2぀のこずが最終的に機胜したした

  1. POSTリク゚ストをGETに倉曎したした。
  2. デヌタにNaN / Null倀が含たれおいたため、モデルを倉曎しおデフォルト倀を指定したした。 これで問題は解決したず思いたす
    この埌、私はこの゚ラヌを受け取るのをやめたした。
    これが誰かを助けるこずができるこずを願っおいたす
このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡