μλ νμΈμ, Flask + Gunicorn + Herokuλ₯Ό μ¬μ©νλ νλ‘λμ μμ μ΄ λ¬Έμ κ° λ°μνμ§λ§ μμΈμ΄λ ν΄κ²° λ°©λ²μ μ°Ύμ§ λͺ»νμ΅λλ€.
POST 맀κ°λ³μκ° μλ νΉμ POST μμ²μ κ²½μ° Heroku λΌμ°ν°μ H18 μ€λ₯(sock=backend)μ ν¨κ» μμ²μ΄ μ€ν¨νμ¬ μλ²κ° μμΌμ λ«μμλ μ λ λ μμΌμ λ«μμμ λνλ λλ€.
μ°λ¦¬λ μ½ 13k νμλ‘ μ’ν λκΉμ§ μ€ν¨ν μλν¬μΈνΈμ μλ΅ ν¬κΈ°λ₯Ό μ€μ΄κΈ° μμνμ΅λλ€. 13k λ―Έλ§μ 보λ΄λ©΄ μλ΅μ΄ νμ μλν©λλ€. 13k μ΄μμ 보λ΄λ©΄ μλ΅μ΄ κ±°μ νμ μλνμ§ μμ΅λλ€.
μ΄λ₯Ό μ¬ννλ μ½λλ https://github.com/erjiang/gunicorn-issue μμ μ¬μ©ν μ μμ΅λλ€. 리ν¬μ§ν 리λ₯Ό Herokuμ μλ κ·Έλλ‘ λ°°ν¬νκ³ READMEμ μ§μΉ¨μ λ°λ₯΄μΈμ.
μ λ§ μ μ©ν λ³΄κ³ μ, @erjiang κ°μ¬ν©λλ€.
ν μ€νΈν heroku κ³μ μ΄ μμ΅λλ€. κ·Έλ° κ³μ μ κ°μ§ μ¬λμ΄ ν μ€νΈν μ μμ΅λκΉ? cc @tilgovi @kennethreitz
κΈ°μμ§λ§ μλ§ κ³§ μ»μ μ μμ κ²μ λλ€.
λΉ λ₯Έ μ¨μ μ± κ²μ¬λ‘ λ‘컬μμ μ€ννκ³ μ¨μ΄νΈλ¦¬μ€μ gunicornμ λΉκ΅νκΈ° μν΄ curlλ‘ λͺ κ°μ§λ₯Ό νμΈνμ΅λλ€.
λ€μμΌλ‘ TCP μμ€μμ μ°¨μ΄κ° μλμ§ κΆκΈν©λλ€. λλ κ·Έκ²λ€μ tcpdumpνκ³ λΉλ¦°λ΄κ° λλ κ²μ μμ차릴 κ²μ λλ€.
λλ κ°μ 컬 λΌμΈμΌλ‘λ gunicornμ΄ μ°κ²°μ λμ§ λ§ μ¨μ΄νΈλ¦¬μ€κ° μ΄μ΄ λ‘λλ€. μμ§ κ·Έ λ¨μκ° μμ§λ§ λ΄κ° λ³Ό μ μμλ κ²μ _μ μΌν_ λ€λ₯Έ μ μ΄μμ΅λλ€.
@tilgovi μ¨μ΄νΈλ¦¬μ€μκ² λ³΄μ΄λ λμμ μ€λ λ μμ μλ‘ μ¬νν μ μλ€κ³ μκ°ν©λλ€. μ΄μ¨λ μ΄λ κ² μ²λ¦¬ν΄μ£Όμ μ κ°μ¬ν©λλ€ :)
μλ
νμΈμ μ¬λ¬λΆ,
κ°μ λ¬Έμ κ° λ°μνμ΅λλ€. μ΄ λ¬Έμ λ₯Ό λ μμΈν κ²ν ν κΈ°νκ° μμΌμ κ°μ?
@tilgovi @erjiang @benoitc
건배
격μΈ
@maximkgn νλΌμ€ν¬λ μ¬μ©νκ³ μμ΅λκΉ? μμΈν λ΄μ©μ?
μ₯κ³ 1.7μ μ¬μ©νκ³ μμ΅λλ€.
μ°λ¦¬λ νμ 13kλ³΄λ€ κΈ΄ νΉμ ν¬μ€νΈ μλ΅μ κ°μ§κ³ μμκ³ ~0.5μ νΉμ νλ₯ λ‘ ν΄λΌμ΄μΈνΈμ μλ΅μ 13kλ³΄λ€ μ½κ° μλ Έμ΅λλ€. heroku λ‘κ·Έμμ λμΌν h18 μ€λ₯λ₯Ό 보μκ³ Python μ½λμμ μ€λ₯κ° λ°μνμ§ μλμ§ νμΈν ν herokuμ Python μ¬μ΄μ gunicorn κ³μΈ΅μμ λ°μνλ€κ³ κ²°λ‘ μ λ΄λ €μΌ νμ΅λλ€.
μ°λ¦¬κ° waitress/uwgiλ‘ μ ννμ λ λ²κ·Έκ° λ°μνμ§ μμμ΅λλ€.
@maximkgn --threads
μ€μ μ μ¬μ©νλ©΄ μ΄λ»κ² λ©λκΉ?
λꡬλ μ§ μ΄κ²μ ν μ€νΈ ν μ μμ΅λκΉ?
νλΌμ€ν¬μ gunicorn(ν μ€νΈ λ²μ 19.3 λ° 19.4.5)μ λμΌν λ¬Έμ κ° μμ΅λλ€. @benoitc 1, 2 λ° 4 μ€λ λ(
μ΄λ€ μμΌλ‘λ μ΄κ²μ ν μ€νΈνλ λ° λμμ μ€ μ μλμ§ μλ €μ£Όμμμ€.
@cbaines μμ²μ΄ μ΄λ»κ² μκ²Όλμ?
Friendpasteλ 1λ°±λ§ κ° μ΄μμ κ²μλ¬Όμ μλ½ν μ μμ΅λλ€.... κ·Έλμ gunicorn λ΄λΆμλ μ νμ΄ μμ΅λλ€.
λ΅μ΄ μμμ΅λλ€. μ¬νν μ μμΌλ―λ‘ λ¬Έμ λ₯Ό λ«μ΅λλ€. νμν κ²½μ° μμ λ‘κ² λ€μ μ½λλ€.
Flask 1.0.2 λ° gunicorn 19.9.0μ ν¬ν¨νλλ‘ μ’ μμ±μ μ λ°μ΄νΈν νμλ κ³μ μ¬μλ©λλ€. νμ§λ§ μ΄κ²μ λν΄ Herokuμ λκ΅°κ°μ κ΄μ¬μ λ°λ κ²μ΄ μ’μ μλ μμ΅λλ€. κ·Έλ€μ νμ μ μΈ Python μ¬λλ€μ΄ μλ€κ³ λ€μμ΅λλ€.
μ¬κΈ°μμ μ΅μ 컀λ°μ μ°Έμ‘°νμμμ€: https://github.com/erjiang/gunicorn-issue/
λν μ κΈ°μ μΌλ‘ λκ·λͺ¨ GET μμ²μ λν΄ μ΄ H18 μ€λ₯λ₯Ό μμ νκ³ μμ΅λλ€.
μ¨μ΄νΈλ¦¬μ€λ‘ μ ννλ©΄ λ¬Έμ κ° ν΄κ²°λμμ΅λλ€. gunicornμ΄ κ·Έκ²μ μμ±νλ μ΄μ λ νμ€νμ§ μμ§λ§ λμΌν μ νν μ½λκ° μ€νλκ³ μμ΅λλ€.
μλ΅ λ³Έλ¬Έμ 21.54KBμ λλ€.
Flask 1.0.2 λ° gunicorn 19.9.0μ ν¬ν¨νλλ‘ μ’ μμ±μ μ λ°μ΄νΈν νμλ κ³μ μ¬μλ©λλ€. νμ§λ§ μ΄κ²μ λν΄ Herokuμ λκ΅°κ°μ κ΄μ¬μ λ°λ κ²μ΄ μ’μ μλ μμ΅λλ€. κ·Έλ€μ νμ μ μΈ Python μ¬λλ€μ΄ μλ€κ³ λ€μμ΅λλ€.
μ¬κΈ°μμ μ΅μ 컀λ°μ μ°Έμ‘°νμμμ€: https://github.com/erjiang/gunicorn-issue/
Herokuμμ μ§μ ν°μΌμ λ§λ€μμ΅λλ€. μ μ©ν κ²μ΄ μμΌλ©΄ μ¬κΈ°μμ μ λ°μ΄νΈν κ²μ λλ€.
@benoitc λ @erjiang μ΄ μ¬ν κ°λ₯ν μλ₯Ό μ 곡ν κ²μ²λΌ 보μ λλ€. μ΄ λ°±μ μ μ΄ μ μμ΅λκΉ?
λ€μ μ΄μμ΅λλ€. λ΄κ° μ€μ€λ‘ ν λΉνκ³ κ°λ₯ν ν μ΄ν΄λ³΄κ² μ΅λλ€.
Flask 1.0.2 λ° gunicorn 19.9.0μ ν¬ν¨νλλ‘ μ’ μμ±μ μ λ°μ΄νΈν νμλ κ³μ μ¬μλ©λλ€. νμ§λ§ μ΄κ²μ λν΄ Herokuμ λκ΅°κ°μ κ΄μ¬μ λ°λ κ²μ΄ μ’μ μλ μμ΅λλ€. κ·Έλ€μ νμ μ μΈ Python μ¬λλ€μ΄ μλ€κ³ λ€μμ΅λλ€.
μ¬κΈ°μμ μ΅μ 컀λ°μ μ°Έμ‘°νμμμ€: https://github.com/erjiang/gunicorn-issue/Herokuμμ μ§μ ν°μΌμ λ§λ€μμ΅λλ€. μ μ©ν κ²μ΄ μμΌλ©΄ μ¬κΈ°μμ μ λ°μ΄νΈν κ²μ λλ€.
herokuμμ λ΅μ₯μ λ°μμ΅λκΉ?
https://github.com/erjiang/gunicorn-issue (gunicorn 19.9.0, Python 2.7.14, sync worker, --workers 4
μ¬μ©)μμ ν
μ€νΈ μΌμ΄μ€λ₯Ό μ¬μ©νμ¬ μ¬νν μ μμμ΅λλ€. μ°Έκ³ λ‘ gunicornμ μ‘μΈμ€ λ‘κ·Έ μΆλ ₯μ HTTP 200μ λ°ννλ€κ³ λ³΄κ³ ν©λλ€.
Python 3.7.3 + gunicorn master
λ‘ μ
λ°μ΄νΈνκ³ --workers 1
μ€μ΄λ κ²μ μ¬νμ±μ μν₯μ λ―ΈμΉμ§ μμμ§λ§ λκΈ°ν μμ
μμμ geventλ‘ μ ννλ©΄ μ€λ₯κ° λ μμ£Ό λ°μν©λλ€(μ¬μ ν λ°μνμ§λ§). --log-level debug
μ¬μ©ν΄λ μ€μν κ²μ λνλμ§ μμμ΅λλ€(μμ² μ€ μ μΌν μΆκ° μΆλ ₯μ [DEBUG] POST /test1
νμ΄μμ΅λλ€).
λ€μμΌλ‘ --spew
μλνμ§λ§ λ¬Έμ κ° λ μ΄μ μ¬νλμ§ μμ΅λλ€. μ΄κ²μ μΆκ°νλ €κ³ μ λ₯Ό μ£Όλ time.sleep(1)
μ κ³Ό resp.close()
μ¬κΈ°μ μ μ¬ λ¬Έμ λ₯Ό λ°©μ§νλν©λλ€.
λ°λΌμ close()
μκ°μ μμΌ λ³΄λ΄κΈ° λ²νΌκ° λΉμ΄ μμ§ μμ μ μμΌλ―λ‘ μλ΅μ΄ μμ€λ μ μμ΅λλ€.
μ°Έκ³ :
close()
λ μ°κ²°κ³Ό κ΄λ ¨λ 리μμ€λ₯Ό ν΄μ νμ§λ§ μ°κ²°μ μ¦μ λ«μ νμλ μμ΅λλ€. μ μμ μ°κ²°μ μ’ λ£νλ €λ©΄shutdown()
μ μ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:
heroku login
μ¬μ©νμ¬ CLIμ λ‘κ·ΈμΈν©λλ€.git clone https://github.com/erjiang/gunicorn-issue && cd gunicorn-issue
heroku create
(μ΄κ²μ 무μμλ‘ μμ±λ μ΄λ¦μ κ°μ§ λ¬΄λ£ Heroku μ±μ μμ±νκ³ heroku
λΌλ git remoteλ₯Ό ꡬμ±ν©λλ€)git push heroku master
curl --data "foo=bar" https://YOUR_GENERATED_APP_NAME.herokuapp.com/test1
(75% μ΄μ μ€ν¨)heroku destroy
λ₯Ό μ€ννμ¬ μ±μ μμ ν©λλ€.@edmorley κ°μ @tilgovi μ¬μ΄λλ 무μμ΄ μλͺ»λμλμ§μ κ·Έλ΄λ―ν μ€λͺ
μ μμ°νλ€. μ¬λ°λ₯Έ μμ μ¬νμ΄ λ¬΄μμΈμ§ μ΄ν΄λ³΄κ³ μ μ μμ΅λκΉ? sock.shutdown()
λ₯Ό μΆκ°νκΈ° μν΄ PRμ μ μΆν μλ μμ§λ§ μ΄κ²μ΄ μ¬λ°λ₯Έ μμ μΈμ§ λλ λ€λ₯Έ μν©μ λΆμ μ μΈ μν₯μ λ―ΈμΉ μ§ μ¬λΆλ₯Ό λ§ν λ§νΌ μΆ©λΆν λͺ¨λ¦
λλ€.
μλ
νμΈμ, 503KB μλ΅ ν¬κΈ°λ‘ λμΌν λ¬Έμ κ° λ°μνμ΅λλ€. μλ΅ λ°μ΄ν°λ JSON λ°°μ΄μ
λλ€.
κ΄μ°°λ λμ μ λ€μκ³Ό κ°μ΅λλ€.
λ€μ λ κ°μ§ λͺ¨λ
λ°νμ νκ²½ μ€μ
meinheld-gunicorn-docker μ΄λ―Έμ§λ Python 3.6.7, Flask 1.0.2, flask-restplus 0.12.1, κ°λ¨ν Flask-cachingμ μ¬μ© νμ¬ _python3.6_μΌλ‘ νκ·Έκ° μ§μ λμμ΅λλ€.
Docker κ΅¬μ± : 3κ°μ CPU, RAM 1024MB
Gunicorn κ΅¬μ± :
https://github.com/benoitc/gunicorn/issues/2015μμ λ€λ₯Έ μ¬λμ΄ meinheld μμ μ κ΅μνμ λ¬Έμ κ° μμκ³ λ€λ₯Έ μμ μ μ νμ μ¬μ©νμ¬ λ¬Έμ λ₯Ό ν΄κ²°νμ΅λλ€. μΌλ°μ μΈ λ¬Έμ κ° μλμ§ κΆκΈν©λλ€. @stapetro λ€λ₯Έ μμ μλ₯Ό μλν μ μμ΅λκΉ?
μλ
νμΈμ @jamadden μ
λλ€ .
κ·νμ μ μμΌλ‘ λ¬Έμ κ° ν΄κ²°λμμ΅λλ€. _gevent_ λ° _gthread_ μμ
μ ν΄λμ€μλ λ¬Έμ κ° μμ΅λλ€. λλ meinheldμμ λ©λ¦¬ μ΄μ¬νμ΅λλ€. λΉ λ₯Έ λ΅λ³κ³Ό λμ κ°μ¬ν©λλ€! :)
μ 체 STR:
- https://signup.heroku.com μμ λ¬΄λ£ Heroku κ³μ μ λ§λμμμ€.
- Heroku CLI μ€μΉ(https://devcenter.heroku.com/articles/heroku-cli μ°Έμ‘°)
heroku login
μ¬μ©νμ¬ CLIμ λ‘κ·ΈμΈν©λλ€.git clone https://github.com/erjiang/gunicorn-issue && cd gunicorn-issue
heroku create
(μ΄κ²μ 무μμλ‘ μμ±λ μ΄λ¦μ κ°μ§ λ¬΄λ£ Heroku μ±μ μμ±νκ³heroku
λΌλ git remoteλ₯Ό ꡬμ±ν©λλ€)git push heroku master
curl --data "foo=bar" https://YOUR_GENERATED_APP_NAME.herokuapp.com/test1
(75% μ΄μ μ€ν¨)- μλ£λλ©΄
heroku destroy
λ₯Ό μ€ννμ¬ μ±μ μμ ν©λλ€.
λ΄ μ±μμ λ§€μ° μ μ¬ν λμμ΄ μμκ³ curl --data λμ curl -Hλ₯Ό μ¬μ©ν λ(GET μμ²μ΄κΈ° λλ¬Έμ) λ΄ μ±(Django, Gunicorn, Heruko)μμ μλνλ€λ κ²μ λ°κ²¬νμ΅λλ€. λλ gunicorn-issue μ±μμ ν μ€νΈνμ§ μμμ΅λλ€. μ΄κ²μ΄ λκ΅°κ°μκ² μ μ©ν μ μλ€κ³ μκ°νμ΅λλ€.
@mikkelhn λ€ . Flask/Flask RestPlus λ° Gunicornμ΄ μλ μ±μ λ€μκ³Ό κ°μ΄ μλν©λλ€. POST μμ²μ μλ΅νλ©΄ [νμ΄λ‘λ > 13kμΈ κ²½μ°] 503 μ€λ₯ κ° λ°μνμ§λ§ μ±μ΄ GETμ μλ΅νλ©΄ μ€λ₯ νμ§ μμ΅λλ€ . μ νν κ°μ μ½λ!
λꡬλ μ§μ΄ λ§€μ° μ±κ°μ νλμ μ€λͺ
ν μ μμ΅λκΉ? μ¨μ΄νΈλ¦¬μ€λ‘ μ ννλ κ²μ΄ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νλ μ μΌν ν΄κ²° λ°©λ²μ
λκΉ? Gunicornμ "μμΌλ‘" μμ νλ κ²μ μ€ν κ°λ₯ν μ루μ
μ΄ μλλΌκ³ μκ°ν©λλ€...
λλ close() μ μ shutdown()μ νΈμΆνκΈ° μν΄ PRμ μ΄μμ΅λλ€. μμ§ν Herokuμμ Gunicornμ΄ κΈ°λ³Έμ μΌλ‘ κ³ μ₯λ¬μ λ Herokuκ° Gunicornμ κ³μ μΆμ²νλ κ²μ μ½κ° μλ±ν©λλ€.
@erijangμ΄ μ¬λ°λ₯΄κ² κΈ°μ ν κ²μ²λΌ Herokuκ° Gunicornμ μ¬μ©ν μ μμ λ Gunicornμ κΆμ₯νλ κ²½μ°: Gunicornμ λν κ°λ¨νκ³ μ€ν κ°λ₯ν λμμ 무μμ
λκΉ(λ° Herokuμμ κ°μ₯ μ ꡬμ±νλ λ°©λ²)?
AFAIK, λ§μ κ³ κ°μ΄ Herokuλ₯Ό μ ννλ μ΄μ λ μλ² μν€ν
μ² λ° κ΅¬μ± μΈλΆ μ 보μ λν κΉμ μ§μμ΄ νμνμ§ μκΈ° λλ¬Έμ
λλ€... :|
@RinaldoNani 무μ¨
@benoitc μ΄ λ¬Έμ λ λ€μμμ μΈκΈν κ²μ²λΌ μ¬λ¬ μμ
μ μ νμ μν₯μ μ€λλ€.
https://github.com/benoitc/gunicorn/issues/840#issuecomment -482491267
μλ νμΈμ @benoitcμ λλ€. λλ μ΄μ κ²μλ¬Όμμ μΈκΈ ν λ°μ κ°μ΄, μ°λ¦¬λ λ΄κ° μ΄ν΄, Gunicorn λκΈ°ν "μΉ"μ μ¬μ©μ μ μ, νμ΄μ¬ / νλΌμ€ν¬ μλ² μΈ‘ μμ© νλ‘κ·Έλ¨ λ°°ν¬μ λν κ΄λ¦¬μκ² Herokuμ μ§μΉ¨ (μ λ€μ, Herokuκ°μ μμ£Ό κ°λ¨ νλΌμ€ν¬ / FlaskRestPlus μμ© νλ‘κ·Έλ¨μ λ°°ν¬ ν λ Έλμ ).
μ±μ λμμ μ΄ μ€λ λμ μ λͺ©μ λ°μν©λλ€.
λ‘컬μμ ν
μ€νΈν κ²°κ³Ό λͺ¨λ κ²μ΄ μ μλνλ©° μ±μ λ¬Έμ μμ΄ 20k μ΄μμ JSONμ μ 곡ν©λλ€. κ·Έλ¬λ μ±μ΄ Herokuμ λ°°ν¬λλ©΄ 503 μ€λ₯ λ¬Έμ κ° μ²΄κ³μ μΌλ‘ λ°μν©λλ€. λ§ κ·Έλλ‘ νΈλν½μ΄ μμ΄λ μΆλ ₯μ΄ μ λ¬λμ§ μμ΅λλ€.
λ€λ₯Έ μ¬λλ€μ΄ μ§μ νλ―μ΄ λ‘κ·Έλ HTTP μμ€μμ λͺ¨λ κ²μ΄ μ μμΈ κ²μ²λΌ 보μ
λλ€(200κ°μ μλ΅ μ½λκ° κΈ°λ‘λ¨).
νμ΄λ‘λκ° 13k λ―Έλ§μ΄λ©΄ Heroku/Gunicornμ΄ μμλλ‘ POSTμ μλ΅ν©λλ€.
μ°λ¦¬λ POST(?!?) λμ μ νΌνκ³ λμ GETμ μ¬μ©νλ€λ @mikkelhn μμ΄λμ΄λ₯Ό λ°λκ³ μ΄κ²μ λ¬Έμ λ₯Ό ν΄κ²°νλ (λ³λ‘ μ’μ§ μμ) λ°©λ²μΈ κ² κ°μ΅λλ€.
μ°λ¦¬λ Gunicorn μ λ¬Έκ°κ° μλλ©° μμ§ν μ°λ¦¬μ κ°λ¨ν μ¬μ© μ¬λ‘κ° "μ¦μ" μλν κ²μ΄λΌκ³ κΈ°λνμ΅λλ€.
μ ν¬μκ² λμμ΄ λ μ μμ΄ μμΌμλ©΄ μμν κ°μ¬νκ² μ΅λλ€. :)
@RinaldoNani Shot in the dark... μμ² μ²λ¦¬κΈ° μ΄λκ°μμ request.data
λͺ¨λ μ½μ΄λ³΄μμμ€. μλ₯Ό λ€μ΄:
@route('/whatever', methods=['POST'])
def whatever_handler():
str(request.data)
return flask.jsonify(...)
κ·Έκ²μ΄ λΉμ μ μ€λ₯μ μν₯μ μ€λκΉ?
μ λ μ§κΈ 2μ£Ό λκ² H18 λ¬Έμ λ‘ λΆμ£Όν ν μ€μ 1μμ μ΄κ²μ μ°κ³ μμ΅λλ€(곡μ νκΈ°λ₯Ό κΈ°λ€λ¦΄ μ μμμ΅λλ€).
λλ κ±°λν λ°μ΄ν° μΈνΈλ‘ μμ νκ³ νλ‘―μ 18Kμμ 20K λ μ½λμ μλ΅ν©λλ€. H18μ λ§€μ° μμμ μ€λ₯λ‘ λ°μνμ΅λλ€. λλλ‘ μ μλνμ§λ§ λͺ¨λ λΈλΌμ°μ μμ "μ½ν μΈ ν€λ κΈΈμ΄κ° μΌμΉνμ§ μμ΅λλ€"κ° λ°μν©λλ€. μ΄ λ¬Έμ μ λν΄ λ Όμλ κ±°μ λͺ¨λ μ루μ μ μλνμ§λ§ μ΄μ΄ μμμ΅λλ€. λ΄κ° μλν λ κ°μ§κ° λ§μΉ¨λ΄ μλνμ΅λλ€.
κ°μ₯ μ μ©ν λκΈ
https://github.com/erjiang/gunicorn-issue (gunicorn 19.9.0, Python 2.7.14, sync worker,
--workers 4
μ¬μ©)μμ ν μ€νΈ μΌμ΄μ€λ₯Ό μ¬μ©νμ¬ μ¬νν μ μμμ΅λλ€. μ°Έκ³ λ‘ gunicornμ μ‘μΈμ€ λ‘κ·Έ μΆλ ₯μ HTTP 200μ λ°ννλ€κ³ λ³΄κ³ ν©λλ€.Python 3.7.3 + gunicorn
master
λ‘ μ λ°μ΄νΈνκ³--workers 1
μ€μ΄λ κ²μ μ¬νμ±μ μν₯μ λ―ΈμΉμ§ μμμ§λ§ λκΈ°ν μμ μμμ geventλ‘ μ ννλ©΄ μ€λ₯κ° λ μμ£Ό λ°μν©λλ€(μ¬μ ν λ°μνμ§λ§).--log-level debug
μ¬μ©ν΄λ μ€μν κ²μ λνλμ§ μμμ΅λλ€(μμ² μ€ μ μΌν μΆκ° μΆλ ₯μ[DEBUG] POST /test1
νμ΄μμ΅λλ€).λ€μμΌλ‘
--spew
μλνμ§λ§ λ¬Έμ κ° λ μ΄μ μ¬νλμ§ μμ΅λλ€. μ΄κ²μ μΆκ°νλ €κ³ μ λ₯Ό μ£Όλtime.sleep(1)
μ κ³Όresp.close()
μ¬κΈ°μ μ μ¬ λ¬Έμ λ₯Ό λ°©μ§νλν©λλ€.λ°λΌμ
close()
μκ°μ μμΌ λ³΄λ΄κΈ° λ²νΌκ° λΉμ΄ μμ§ μμ μ μμΌλ―λ‘ μλ΅μ΄ μμ€λ μ μμ΅λλ€.(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
λμμ΄ λκΈ°λ₯Ό λ°λλλ€ :-)