Gunicorn: ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ ํ›„ ์ฆ‰๊ฐ์ ์ธ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ

์— ๋งŒ๋“  2013๋…„ 08์›” 08์ผ  ยท  45์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: benoitc/gunicorn

Heroku์˜ Django ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•ž์—์„œ Gunicorn์ด ์‹คํ–‰๋˜๋Š” ์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ์™€ ๊ด€๋ จ๋œ ๋งค์šฐ ์ด์ƒํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ณธ์งˆ์ ์œผ๋กœ ์ด ๋ฌธ์ œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋งค์šฐ ์˜ค๋ž˜ ์‹คํ–‰๋˜๋Š” ์š”์ฒญ์ด ์žˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜์—ฌ 30์ดˆ ํ›„์— Heroku์˜ ํ”Œ๋žซํผ ์ˆ˜์ค€ ์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋กœ ์ธํ•ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ทธ ์ž์ฒด๋กœ ๋ฌธ์ œ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์€ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ ๋ฌธ์ œ๋Š” ํ›„์† ์š”์ฒญ์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ _after_ ๋ฐœ์ƒํ•˜๋Š” ์š”์ฒญ์ด ์ฆ‰์‹œ ๋‹ค์Œ ํ˜•์‹์˜ Gunicorn ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

[CRITICAL] WORKER TIMEOUT (pid:15)

์ด๋กœ ์ธํ•ด ๋‚ด๋ถ€ ์„œ๋ฒ„ ์˜ค๋ฅ˜ ํŽ˜์ด์ง€๊ฐ€ ํด๋ผ์ด์–ธํŠธ์— ์ฆ‰์‹œ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด ๋™์ž‘์€ ์ผ๊ด€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ์š”์ฒญ์ด ์„ฑ๊ณตํ•  ๋•Œ๋„ ์žˆ๊ณ  ๊ทธ๋ ‡์ง€ ์•Š์„ ๋•Œ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ–ˆ๋˜ ๋™์ผํ•œ Gunicorn ์ž‘์—…์ž๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์„๊นŒ ํ•˜๋Š” ์˜์‹ฌ์ด ๋“ญ๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด Django์—์„œ ์ง์ ‘ Gunicorn์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

python app/manage.py run_gunicorn -b 0.0.0.0:$PORT -w 2 -k gevent

worker_connections ๋ฐ max_requests์™€ ๊ฐ™์€ ๊ธฐํƒ€ ๊ด€๋ จ ๊ตฌ์„ฑ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ์„ค์ •๊ณผ ์ž‘์—…์ž ์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ์‹คํ—˜ํ–ˆ์ง€๋งŒ ์‹œ๋„ํ•œ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์œ„์—์„œ ์„ค๋ช…ํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ Gunicorn ๋ฒ„์ „์€ 0.14.6์ด๋ฉฐ ๋ฌธ์ œ์˜ ์›์ธ์ธ ๊ฒฝ์šฐ 17.5๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ•œ ํ›„ ๋กค๋ฐฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ๋‘ ๋ฒ„์ „์—์„œ ๋™์ผํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜ ๊ทผ๋ณธ ์›์ธ์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ํฐ ์–ด๋ ค์›€์„ ๊ฒช๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์— ๋งํฌ๋œ Heroku ๋ฌธ์„œ์—์„œ:

๋ผ์šฐํ„ฐ๊ฐ€ ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋™์•ˆ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ์ฒ˜๋ฆฌ ์ค‘์ธ ์š”์ฒญ์ด ์‹œ๊ฐ„ ์ œํ•œ์— ๋„๋‹ฌํ–ˆ์Œ์„ ์•Œ์ง€ ๋ชปํ•˜๋ฉฐ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ ๊ณ„์†ํ•ด์„œ ์š”์ฒญ์— ๋Œ€ํ•ด ์ž‘์—…ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์›๋ž˜ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์ด ํด๋ผ์ด์–ธํŠธ์˜ ๊ด€์ ์—์„œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋˜์—ˆ๋‹ค๋Š” ์‚ฌ์‹ค์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  Gunicorn ์ž‘์—…์ž๊ฐ€ ์—ฌ์ „ํžˆ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋ฅผ ๋‹นํ™ฉํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๊ฒƒ์€ ์ž‘์—…์ž๊ฐ€ gevent๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋”ฐ๋ผ์„œ ๋น„๋™๊ธฐ ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์ฆ‰์‹œ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ์ƒˆ๋กœ์šด ํ›„์† ์š”์ฒญ์„ ๋ฐœ์ƒ์‹œํ‚ฌ ๊ฒƒ์ธ์ง€์ž…๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ฒซ ๋ฒˆ์งธ ์žฅ๊ธฐ ์š”์ฒญ์ด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. ์—ฌ๋Ÿฌ ์ž‘์—…์ž gevent ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค๋กœ ์ธํ•œ ๋น„์ฐจ๋‹จ ๋ฐ
  2. Gunicorn์˜ ๊ธฐ๋ณธ ์š”์ฒญ ์ œํ•œ ์‹œ๊ฐ„์€ 30์ดˆ์ด๋ฏ€๋กœ ํ›„์† ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๊ธฐ ์ „์— Gunicorn์— ์˜ํ•ด ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” Heroku์˜ ์ž์ฒด ์š”์ฒญ ์ œํ•œ ์‹œ๊ฐ„๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์ด PostgreSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์—ฐ๊ฒฐ๋˜๊ณ  ์—ฌ๋Ÿฌ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ์ ์„ ์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถฉ๋Œ์€ DB์™€ ์ธํ„ฐํŽ˜์ด์Šคํ•˜๋Š” ๋™์•ˆ Heroku ๋•๋ถ„์— ์žฅ๊ธฐ ์‹คํ–‰ ์—ฐ๊ฒฐ ์‹œ๊ฐ„์ด ์ดˆ๊ณผ๋œ ํ›„์—๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์—์„œ ๋‘ ๊ฐœ์˜ ๊ฐœ๋ณ„ ๋ณด๊ธฐ๋ฅผ ๋งŒ๋“ค์–ด ํ…Œ์ŠคํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ํ•˜๋‚˜๋Š” Heroku ์‹œ๊ฐ„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ๋Œ€ํ•ด ๊ธด ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค๋ฅธ ํ•˜๋‚˜๋Š” Heroku ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด 30์ดˆ ํ‘œ์‹œ๋ฅผ ๋‹จ์ˆœํžˆ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์ด์ „ ๋ณด๊ธฐ๋Š” ๋‹ค์Œ ์š”์ฒญ์—์„œ Gunicorn ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์œ ๋ฐœํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ '์ž ์ž๊ธฐ' ๋ณด๊ธฐ๋Š” ๊ทธ๋ ‡์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ ์ด ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค๋Š” ๊ธฐ๋ณธ ๋™์ž‘์— ๋Œ€ํ•œ ํ†ต์ฐฐ๋ ฅ์ด ์žˆ์œผ๋ฉด ํ™˜์ƒ์ ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ์ถ”๊ฐ€ ์ •๋ณด๊ฐ€ ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ์ด๊ฒƒ์ด ๊ทธ๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•์ด๋ฉฐ ์ด์ „์— ์ œ๊ธฐ/์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์•˜์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

( FeaturWorker - Bugs -

๋ชจ๋“  45 ๋Œ“๊ธ€

@Jwpe ์šฐ์ˆ˜ํ•œ ๋ฒ„๊ทธ ๋ณด๊ณ ์„œ.

๊ฐ€์žฅ ๋จผ์ € ์‚ดํŽด๋ณผ ๊ฒƒ์€ ์นœํ™˜๊ฒฝ PostgreSQL ๋“œ๋ผ์ด๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ์›์ˆญ์ด ํŒจ์น˜์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ํŠน์ • ๋ฒ„์ „์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ์ƒํ™ฉ์€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ถ™์—ฌ ๋„ฃ์€ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋Š” ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ์ด๋ฉฐ ๊ธฐ๋ณธ์ ์œผ๋กœ "๊ทธ๋ฆฐ๋ ›์ด $timeout ์ดˆ ์ด์ƒ ๋™์•ˆ ์–‘๋ณดํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค"๋กœ ์š”์•ฝ๋˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์ž ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ์žฅ๊ธฐ ์‹คํ–‰ PostgreSQL ์š”์ฒญ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ์กฐ์‚ฌํ•  ์œ„์น˜์ž…๋‹ˆ๋‹ค.

@davisp ์ด์— ๋Œ€ํ•œ ์‹ ์†ํ•œ ๋‹ต๋ณ€์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

๊ท€ํ•˜์˜ ํฌ์ธํ„ฐ๋ฅผ ๋”ฐ๋ผ Django ์•ฑ์„ Postgres์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” psycopg2 ์–ด๋Œ‘ํ„ฐ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ฌธ์„œ ์„น์…˜์„ ๋ฐœ๊ฒฌ

๊ฒฝ๊ณ : Psycopg ์—ฐ๊ฒฐ์€ ๋…น์ƒ‰ ์Šค๋ ˆ๋“œ๋กœ๋ถ€ํ„ฐ ์•ˆ์ „ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๋‹ค๋ฅธ ๋…น์ƒ‰ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๋‹น ํ•˜๋‚˜์˜ ์ปค์„œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•œ ๋ฒˆ์— ๋‘˜ ์ด์ƒ์˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค(๋˜๋Š” 2.4.2 ์ด์ „ ๋ฒ„์ „์—์„œ๋Š” ๊ต์ฐฉ ์ƒํƒœ).
๋”ฐ๋ผ์„œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ฝ”๋ฃจํ‹ด ๊ฐ„์˜ ์—ฐ๊ฒฐ ๊ณต์œ ๋ฅผ ํ”ผํ•˜๊ฑฐ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์นœํ™”์ ์ธ ์ž ๊ธˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ณต์œ  ์—ฐ๊ฒฐ(์˜ˆ: ํ’€๋ง)์„ ๋™๊ธฐํ™”ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ฆ‰, psycopg2๋Š” ๋…น์ƒ‰ ์Šค๋ ˆ๋“œ๋ฅผ ์ข‹์•„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•œ ๋™์ž‘์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ด๊ฒƒ์ด ์˜ค๋ฅ˜์˜ ์›์ธ์ด๋ผ๊ณ  ์ถ”์ธกํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. psycopg ๋ฌธ์„œ์— ๋”ฐ๋ฅด๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์ œ์•ˆ๋œ ๋ฐฉ๋ฒ•์€ ์ฝ”๋ฃจํ‹ด์— ๋Œ€ํ•œ psycopg ์ง€์›์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ถŒ์žฅ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” psycogreen ์ž…๋‹ˆ๋‹ค.

psycogreen ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ…Œ์ŠคํŠธ ์„œ๋ฒ„์—์„œ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๊ณ  ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๋น„๊ต์  ๋นจ๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@Jwpe ๊ธฐ์–ตํ•˜๊ณ  ์žˆ๋˜ ํ›… ๊ฐ™๋„ค์š”.

@benoitc ์•„๋งˆ๋„ Gunicorn ๋ฌธ์„œ ์–ด๋”˜๊ฐ€์—์„œ ์ด๊ฒƒ์„ ๋ถˆ๋Ÿฌ์•ผ ํ• ๊นŒ์š”? ๊ฐ€์žฅ ์ข‹์€ ์žฅ์†Œ๊ฐ€ ์–ด๋””์ธ์ง€๋Š” ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@davisp FAQ ์„น์…˜์— ์žˆ์Šต๋‹ˆ๊นŒ?

hmppff๋Š” ์ด๋ฏธ ์กด์žฌํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์žŠ์–ด๋ฒ„๋ ธ์Šต๋‹ˆ๋‹ค(http://docs.gunicorn.org/en/latest/faq.html). ๊ทธ๋ž˜์„œ ๊ฑฐ๊ธฐ์—์„œ "๋ฌธ์ œ ํ•ด๊ฒฐ" ์„น์…˜์— ๋Œ€ํ•œ ๋งํฌ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์ด๋Ÿฌํ•œ ์„น์…˜์—์„œ virtualenv ๋ฐ ๊ธฐํƒ€ ํŠธ๋ฆญ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์ด๋™ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฝ๊ณ  ๋˜๋Š” "๋…น์ƒ‰ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•œ ์ฐธ๊ณ  ์‚ฌํ•ญ" ํŽ˜์ด์ง€์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šˆํผ ํ”„๋ ˆ์‹ฑ์ด ์•„๋‹™๋‹ˆ๋‹ค.

๋‚˜๋Š” gevent ์ž‘์—…์ž์™€ ๋‹ค๋ฅธ ์ž‘์—…์ž์™€ ํ•จ๊ป˜ gunicorn์„ ์‹คํ–‰ํ•˜๋Š” Heroku์—์„œ ๊ฑฐ์˜ ๋™์ผํ•œ ๋™์ž‘์„ ๋ณด๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ์Šค๋ ˆ๋“œ์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๋Œ€๋กœ ๋™๊ธฐ ์ž‘์—…์ž๋กœ ์ „ํ™˜ํ–ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋™์ผํ•œ ์‹ฌ๊ฐํ•œ ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. H12 30์ดˆ Heroku ์ปท์˜คํ”„๋ฅผ ์–ป์€ ๋‹ค์Œ ์ „์ฒด dyno๋ฅผ ์žฌ์„ค์ •ํ•  ๋•Œ๊นŒ์ง€(๋•Œ๋กœ๋Š” ํ•œ ์‹œ๊ฐ„ ์ด์ƒ ๋˜๋Š” ์ตœ๋Œ€ ์š”์ฒญ์— ๋„๋‹ฌํ•  ๋•Œ๊นŒ์ง€) H12 ๋ฐ [CRITICAL] Worker Timeout ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜๋ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ €๋Š” gunicorn ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ 28์ดˆ๋กœ ์กฐ์ •ํ•˜์—ฌ Heroku๊ฐ€ ๊ทธ๊ฒƒ์„ ๋Š๊ธฐ ์ „์— ์‹œ๊ฐ„ ์ดˆ๊ณผ๋˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋™์ผํ•œ(๋˜๋Š” ๋งค์šฐ ์œ ์‚ฌํ•œ) ๋ฌธ์ œ๊ฐ€ ํ•˜๋ฃจ์— ํ•œ ๋ฒˆ ๋˜๋Š” ๋‘ ๋ฒˆ ๋ฐœ์ƒํ•˜๊ณ  ๋งˆ์Šคํ„ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋  ๋•Œ๊นŒ์ง€ ์ง€์†๋ฉ๋‹ˆ๋‹ค. ์ด๋ฒˆ์—๋Š” gunicorn์ด ๋Š๊ธฐ ๋•Œ๋ฌธ์— H13(์—ฐ๊ฒฐ ๋‹ซํž˜)์œผ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ด ์‹œ๊ฐ„ ๋™์•ˆ ํŠธ๋ž˜ํ”ฝ์ด ํฌ๊ฒŒ ๊ธ‰์ฆํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ํ˜„์žฌ procfile ํ•ญ๋ชฉ์ž…๋‹ˆ๋‹ค.

web: newrelic-admin run-program gunicorn publisher.wsgi -b 0.0.0.0:$PORT -w 4 --max-requests 1000 --timeout 28 --preload

์ผ๋ จ์˜ ์ด๋ฒคํŠธ ์„ธ๋ถ€์ •๋ณด:

๋จผ์ €, ์ •๋ง ๊ธด(5์ดˆ ์ด์ƒ) ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ๋ช‡ ๊ฐ€์ง€ ์š”์ฒญ์„ ๋ฐ›์€ ๋‹ค์Œ H12 ์‹œ๊ฐ„ ์ดˆ๊ณผ(์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋กœ ์ธํ•ด ๋Š๊น€)์™€ ํ•จ๊ป˜ ์š”์ฒญ์ด ์‹คํŒจํ•˜๊ณ  ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์š”์ฒญ์ด ์™„๋ฃŒ๋˜์ง€๋งŒ ์˜ˆ์™ธ์ ์œผ๋กœ ๊ธด ์‹œ๊ฐ„(20 ์ดˆ). ๊ทธ๋•Œ๋ถ€ํ„ฐ ๋‹ค์ด๋…ธ๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ•  ๋•Œ๊นŒ์ง€ ์ˆœ์ˆ˜ํ•œ H11 30์ดˆ heroku ์ปท์˜คํ”„์ž…๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” (python/django๋ฅผ ์‹คํ–‰ํ•˜๋Š”) ์›น์„œ๋ฒ„๋กœ gunicorn(v 18.0)์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์šดํƒ€์ž„๊ณผ ์—„์ฒญ๋‚˜๊ฒŒ ๋Š˜์–ด๋‚œ ์š”์ฒญ ๋Œ€๊ธฐ์—ด ์‹œ๊ฐ„์„ ๋ณด์—ฌ์ฃผ์ง€๋งŒ ๋‹ค๋ฅธ ํ†ต์ฐฐ๋ ฅ์€ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” newrelic์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. NR์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ฒ˜๋ฆฌ๋Ÿ‰์ด๋‚˜ ๊ธฐํƒ€ ๋น„์ •์ƒ์ ์ธ ์กฐ๊ฑด์˜ ์ŠคํŒŒ์ดํฌ๋Š” ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋กœ๊ทธ ์ฒ˜๋ฆฌ ๋ฐ ์˜ค๋ฅ˜ ์ด๋ฉ”์ผ ๋ฐœ์†ก์„ ์œ„ํ•ด ํŽ˜์ดํผํŠธ๋ ˆ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Oct 15 15:08:53 nutrislice-stockton heroku/router: at=info method=GET path=/marketingtools/api/slides/?format=json-p&callback=_jqjsp&_1381871332239= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=15ms service=216ms status=200 bytes=21 Oct 15 15:08:54 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871332232= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=2ms service=90ms status=200 bytes=231 Oct 15 15:08:56 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871323514= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=3ms service=94ms status=200 bytes=5986 Oct 15 15:09:03 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="54.247.188.179" dyno=web.2 connect=3ms service=23ms status=200 bytes=0 Oct 15 15:09:13 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871237946= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=5ms service=166ms status=200 bytes=468 Oct 15 15:09:20 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871323611= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=6ms service=183ms status=200 bytes=453 Oct 15 15:09:40 nutrislice-stockton heroku/router: at=info method=GET path=/ host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=1ms service=260ms status=200 bytes=35951 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/87/menu-type/43/?format=json-p&callback=jQuery18008709754704032093_1381871379465&_=1381871393589 host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=15ms service=129ms status=200 bytes=400 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/306/menu-type/187/?format=json-p&callback=jQuery180013075259909965098_1381873891397&_=1381873896600 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=2ms service=33ms status=200 bytes=486 Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/186/?smp=257 host=coppellisd.nutrislice.com fwd="76.199.114.157" dyno=web.2 connect=7ms service=103ms status=200 bytes=323 Oct 15 15:10:00 nutrislice-stockton app/web.2: INFO http://stockton.nutrislice.com/heartbeat/ Pinged from IP: 10.190.159.205 -- AGENT: NewRelicPinger/1.0 (269661) Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="50.112.95.211" dyno=web.2 connect=1ms service=10ms status=200 bytes=0 Oct 15 15:10:09 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/239/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=8ms service=334ms status=200 bytes=277 Oct 15 15:10:16 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=1ms service=96ms status=200 bytes=245 Oct 15 15:10:20 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/391/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=32ms service=5207ms status=200 bytes=290 Oct 15 15:10:22 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/350/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=60ms service=7676ms status=200 bytes=1147 Oct 15 15:10:31 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/258/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=42ms service=517ms status=200 bytes=26974 Oct 15 15:10:43 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871432885= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1490ms service=9883ms status=200 bytes=1565 Oct 15 15:10:52 nutrislice-stockton heroku/router: at=error code=H13 desc="Connection closed without response" method=GET path=/ host=jordandistrict.nutrislice.com fwd="71.199.48.37" dyno=web.2 connect=1959ms service=29230ms status=503 bytes=0 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [26] [INFO] Booting worker with pid: 26 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50,930 (26/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:10:54 nutrislice-stockton heroku/router: at=info method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871433429= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1181ms service=20074ms status=200 bytes=32 Oct 15 15:10:55 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871433374= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1136ms service=20393ms status=200 bytes=142 Oct 15 15:11:01 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:01 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871432922= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1435ms service=23198ms status=200 bytes=486 Oct 15 15:11:03 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:11:03 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:05 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871443300= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1089ms service=20040ms status=200 bytes=268 Oct 15 15:11:10 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/135/menu-type/63/2013/10/14/?format=json-p&callback=_jqjsp&_1381871439548= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1018ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871443267= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1096ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871443296= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1108ms service=30000ms status=503 bytes=0 Oct 15 15:11:23 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/weeks/school-menu-profile/48/menu-type/21/2013/10/14/?format=json-p&callback=_jqjsp&_1381871449451= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1114ms service=31756ms status=200 bytes=48771 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871455129= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=990ms service=30001ms status=503 bytes=0 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871455291= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=1028ms service=30008ms status=503 bytes=0 Oct 15 15:11:31 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/179/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2492ms service=30000ms status=503 bytes=0 Oct 15 15:11:32 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/192/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2713ms service=30003ms status=503 bytes=0 Oct 15 15:11:39 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/ host=hebisd.nutrislice.com fwd="38.107.226.1" dyno=web.2 connect=2115ms service=30001ms status=503 bytes=0 Oct 15 15:11:45 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/44/menu-type/19/2013/10/14/?format=json-p&callback=_jqjsp&_1381871472583= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=2168ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871476287= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1927ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871476543= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2117ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871476481= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2111ms service=30009ms status=503 bytes=0 Oct 15 15:11:50 nutrislice-stockton app/web.2: 2013-10-15 15:11:32,597 (26/NR-Activate-Session/nutrislice-stockton) newrelic.core.data_collector INFO - Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:50 nutrislice-stockton app/web.2: INFO Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:52 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871480294= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1689ms service=30006ms status=503 bytes=0 Oct 15 15:11:55 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871482566= host=henrico.nutrislice.com fwd="72.84.233.45" dyno=web.2 connect=2067ms service=30004ms status=503 bytes=0 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [29] [INFO] Booting worker with pid: 29 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41,067 (29/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [32] [INFO] Booting worker with pid: 32 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44,154 (32/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [35] [INFO] Booting worker with pid: 35 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48,273 (35/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=21ms service=76ms status=200 bytes=255 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [38] [INFO] Booting worker with pid: 38 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54,388 (38/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:12:00 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:12:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:12:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:02 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:12:02 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3650ms service=30006ms status=503 bytes=0 Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3581ms service=30006ms status=503 bytes=0 Oct 15 15:12:06 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871492466= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3582ms service=30001ms status=503 bytes=0 Oct 15 15:12:09 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=pasco.nutrislice.com fwd="173.65.148.9" dyno=web.2 connect=3837ms service=30004ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3987ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871497105= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3962ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871497128= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=4020ms service=30007ms status=503 bytes=0
๊ทธ๋ฆฌ๊ณ  ์ด H12 ํƒ€์ž„์•„์›ƒ๊ณผ [CRITICAL] WORKER TIMEOUT์˜ "์ฃฝ์Œ์˜ ๋‚˜์„ ํ˜•"์€ ๋งˆ์Šคํ„ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋  ๋•Œ๊นŒ์ง€ ๊ณ„์†๋ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ๊ฐ™์€ ๋ฌธ์ œ์ด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๋ผ๋ฉด ์–ด๋–ค ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์ˆ˜์ •ํ•  ์ œ์•ˆ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” gunicorn์ด ์‹œ๊ฐ„ ์ดˆ๊ณผ ํ›„ ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์ƒˆ๋กœ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ •์ƒ์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ทธ ์ดํ›„์—๋Š” ์š”์ฒญ์ด ๋„์ฐฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ Heroku ๋ฌธ์ œ ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

:+1: ์ด ๋ฌธ์ œ๋„ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

Heroku์—์„œ๋„ ์ด ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@sprynmr @richardkeen gunicorn ์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๋กœ๊ทธ๋ฅผ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋งŽ์€ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@nebstrebor ์š”์ฒญ ์ˆ˜๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š์œผ๋ฉด ์–ด๋–ป๊ฒŒ ๋˜๋‚˜์š”?

์šฐ๋ฆฌ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค.
web: newrelic-admin run-program python manage.py run_gunicorn -b "0.0.0.0:$PORT" --log-level=DEBUG -w 3 -k gevent --max-requests 250

๋กœ๊ทธ ์ˆ˜์ค€ DEBUG๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ์šฐ๋ฆฌ๋Š” ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€์— ๋Œ€ํ•œ ๋กœ๊ทธ๋ฅผ ๋งŽ์ด ์–ป์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ๋กœ์„œ๋Š” gevent ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์ง€๋งŒ ์ด์ƒ์ ์ด์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.

@sprynmr ์ตœ๋Œ€ ์š”์ฒญ ์ˆ˜๋ฅผ ์ œ๊ฑฐํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”? ๋˜ํ•œ ์–ด๋–ค ๋ฒ„์ „์˜ gevent?

์šฐ๋ฆฌ๋Š” 1.0rc2 ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ตœ๋Œ€ ์š”์ฒญ ์ˆ˜๋Š” ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ๋‹ค์‹œ ์ผœ๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์š”์ฒญ ์ œํ•œ ์‹œ๊ฐ„ ์— ๋Œ€ํ•œ Heroku ํŽ˜์ด์ง€๋ฅผ ์ฝ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ œํ•œ ์‹œ๊ฐ„ well under 30 seconds, such as 10 or 15 ์„ ์„ค์ •ํ•˜๋„๋ก ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค. gunicorn์—์„œ timeout ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ œ์•ˆ์„ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๊นŒ?

์–ด์จŒ๋“  gevent์— ๋‚˜ํƒ€๋‚˜๋Š” ๋ฌธ์ œ๋Š” ์•„๋งˆ๋„ ์—ฐ๊ฒฐ์ด ์ฒ˜๋ฆฌ๋˜๋Š” ๋ฐฉ์‹ ๋•Œ๋ฌธ์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ˜„์žฌ ๋ฒ„์ „์˜ ์ž‘์—…์ž๋Š” ์ด ๊ทธ๋ฆฐ๋ ›์˜ ์‹ค์ œ ๊ฐ๋… ์—†์ด ๊ทธ๋ฆฐ๋ ›/์—ฐ๊ฒฐ์„ ์ˆ˜๋ฝํ–ˆ์Šต๋‹ˆ๋‹ค. ์•„๋งˆ๋„ ํ—ˆ์šฉ๋œ ์†Œ์ผ“ ์ค‘ ํ•˜๋‚˜๊ฐ€ ์˜ค๋žซ๋™์•ˆ ๋Œ€๊ธฐํ•˜๊ณ  ๋‹ค๋ฅธ ์ด๋ฒคํŠธ๊ฐ€ ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์•„ gunicorn ์ž‘์—…์ž๊ฐ€ ๋‹ค์‹œ ์‹œ์ž‘๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทผ๋ฐ ํ™•์ธํ•ด์•ผ์ง€..

ํฅ๋ฏธ๋กœ์šด. ์•„๋‹ˆ์š”, ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

:+1: ๋‚ด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋„ ์ด๊ฒƒ์„ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. @Jwpe / @sprynmr ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ™œ๋™์ด ๋ฐœ์ƒํ•œ ์ง€ 2๊ฐœ์›”์ด ๋„˜์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์œผ์…จ๋‹ค๋ฉด ๋“ฃ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”!

@dencold ์‹œ๋„ํ•ด ๋ณด์…จ์Šต๋‹ˆ๊นŒ https://github.com/benoitc/gunicorn/issues/588#issuecomment -29267541

๋‚˜๋Š” heroku์— ๊ณ„์ •์ด ์—†์œผ๋ฏ€๋กœ ๊ทธ๊ฒƒ์ด ๋ฌด์—‡์„ ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋™์ผํ•œ ๋กœ๊ทธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š” @benoitc๋‹˜ , ๋น ๋ฅธ ๋‹ต๋ณ€์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ๋กœ๊ทธ๋Š” @Jwpe ๋ฐ @nebstrebor๊ฐ€ ๋ณด๊ณ ํ•œ ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๊ฒฝ์šฐ ๊ด€๋ จ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€ ์—ฌ๊ธฐ์— ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์•Œ๋ ค์ฃผ์‹œ๋ฉด ๊ฐ์‚ฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด์ „ ์˜๊ฒฌ์—์„œ ์กฐ์–ธ์„ ๋ฐ›์•„ gunicorn ์ œํ•œ ์‹œ๊ฐ„์„ heroku ๋ผ์šฐํ„ฐ ์ œํ•œ ์‹œ๊ฐ„๋ณด๋‹ค ๋‚ฎ๊ฒŒ ๊ตฌ์„ฑํ•˜๊ณ  ๋„์›€์ด ๋˜๋Š”์ง€ ํ™•์ธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ œ์•ˆํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ณ„๋‹จ์‹ ์‹คํŒจ์˜ ์‹ค์ œ ์›์ธ์„ ์ฐพ๋Š” ๊ฒƒ์ด ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•œ ์ž‘์—…์ž๊ฐ€ ์‹คํŒจํ•˜๊ณ  ์ „์ฒด gunicorn ์„œ๋ฒ„๊ฐ€ ์™„์ „ํžˆ ์‘๋‹ตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณด๋Š” ๊ฒƒ์€ ์ •๋ง ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ์ง„๋‹จ์„ ๋•๊ธฐ ์œ„ํ•ด ๋‚ด๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ์žˆ์œผ๋ฉด ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค. ์ด ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋กœ์ปฌ์—์„œ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. heroku ์ธํ”„๋ผ์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค @dencold ์†”๋ฃจ์…˜์„ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๋งค์šฐ ์‹ฌ์˜คํ•˜๊ณ  ์‹ ๋น„ํ•œ ๋ฒ„๊ทธ์ฒ˜๋Ÿผ ๋ณด์˜€๊ณ  ๋‚˜๋Š” ๊ทธ๊ฒƒ๊ณผ ์‹ธ์šธ ์‹œ๊ฐ„์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ž„์•„์›ƒ ๋น„ํŠธ๊ฐ€ ๋„์›€์ด ๋˜๋Š”์ง€ ๊ถ๊ธˆํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋ณด๊ณ ํ•ฉ๋‹ˆ๋‹ค.

@dencold ๋„ˆ๋„ ์ƒˆ ์œ ๋ฌผ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ˆ?

@benoitc ๋„ค, ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ์ƒˆ๋กœ์šด ์œ ๋ฌผ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

@dencold ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ด ๋ฌธ์ œ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜์˜ ์›์ธ์„ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ํˆฌ์žํ•  ์‹œ๊ฐ„์ด ์—†์—ˆ๊ณ  ์›๋ž˜ ์š”์ฒญ์˜ ๊ธฐ๊ฐ„์„ ์ค„์ด๋Š” ๋ฐ ์ง‘์ค‘ํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์˜ค๋ฅ˜์˜ ์‹ฌ๊ฐํ•œ ํŠน์„ฑ(์‚ฌ์šฉ์ž๊ฐ€ ์ง๋ฉดํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—)์œผ๋กœ ์ธํ•ด ์ผ์‹œ์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด WSGI ์„œ๋ฒ„๋ฅผ ์ „ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฌธ์ œ๋ฅผ ์ถ”๊ฐ€๋กœ ๋ถ„๋ฅ˜ํ•˜๊ธฐ ์œ„ํ•ด ๋” ์ด์ƒ ์‹คํ—˜์„ ์‹คํ–‰ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

@Jwpe ์ตœ์†Œํ•œ ์ œ์•ˆ๋œ ์†”๋ฃจ์…˜์„ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๊นŒ? ๋˜ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•˜๊ณ  ๋‚˜๋Š” gunicorn ์ž์ฒด๋กœ ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ฐจ๋‹จ ์‹œ๊ฐ„์ด 15์ดˆ๋กœ ์ค„์—ˆ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

2014๋…„ 1์›” 26์ผ ์ผ์š”์ผ, Benoit Chesneau [email protected]
์ผ๋‹ค:

@Jwpe https://github.com/Jwpe ์ ์–ด๋„ ์ œ์•ˆ์„ ์‹œ๋„ ํ–ˆ์Šต๋‹ˆ๊นŒ?
ํ•ด๊ฒฐ์ฑ…? ๋˜ํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ด์ƒํ•˜๊ณ  gunicorn์œผ๋กœ ์žฌํ˜„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๊ทธ ์ž์ฒด๋กœ.

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ Gi tHubhttps://github.com/benoitc/gunicorn/issues/588#issuecomment -33316333์—์„œ ํ™•์ธํ•˜์„ธ์š”.
.

๋ฒค ๋กœ๋ฒ„์ธ 
CTO
์ฃผ์‹ํšŒ์‚ฌ ๋‰ดํŠธ๋ฆฌ์Šฌ๋ผ์ด์Šค
866-524-3444 ๋‚ด์„  702
[email protected]

@Jwpe / @nebstrebor ์ด ๋ฌธ์ œ์— ๋Œ€ํ•ด ๋‹ค์‹œ

@benoitc ์šฐ๋ฆฌ๋Š” heroku ์ธ์Šคํ„ด์Šค์— ์ œ์•ˆ๋œ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์†”๋ฃจ์…˜์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•ž์œผ๋กœ ๋ฉฐ์น  ๋™์•ˆ ์ด๊ฒƒ์„ ์ฃผ์˜ ๊นŠ๊ฒŒ ๊ด€์ฐฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ƒˆ๋กœ์šด ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์ ์šฉ๋œ ํ›„ ๋™์ผํ•œ ๋ฌธ์ œ ํŒ์—…์ด ํ‘œ์‹œ๋˜๋ฉด ๋‹ค์‹œ ๊ฒŒ์‹œํ•ฉ๋‹ˆ๋‹ค.

๋„์›€์„ ์ฃผ์‹  ๋ชจ๋“  ๋ถ„๋“ค๊ป˜ ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ๋Š” ์œ ์ผํ•œ ์‚ฌ๋žŒ์ด ์•„๋‹ˆ๋ผ๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ฒŒ ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›์ธ์˜ ๋ฐ”๋‹ฅ์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

@benoitc ๋Š” ๋” ๋‚ฎ์€ ์‹œ๊ฐ„ ์ œํ•œ์ด ์ง€๋‚ฌ์Œ ์„ ๋ณด๊ณ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋ณด์•˜์ง€๋งŒ ์ „์ฒด gunicorn ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‘๋‹ตํ•˜์ง€ ์•Š๊ฒŒ ๋˜๋Š” ์›์ธ์€ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ 30์ดˆ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋กœ ์ธํ•ด ์ฒ˜์Œ์— ๊ณ„๋‹จ์‹ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ ์ด์œ ๋ฅผ ์•„์ง ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ณ„์†ํ•ด์„œ ์†Œ์‹์„ ์ „ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ๋„์›€์— ๋‹ค์‹œ ํ•œ ๋ฒˆ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

Raspberry PI์—์„œ gunicorn์œผ๋กœ Django๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋™์ผํ•œ [CRITICAL] WORKER TIMEOUT ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ฌด์†Œ์‹.

๋™์ผํ•œ [์ค‘์š”] ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์ œ๋Š” ์ž‘์—…์ž์˜ ์‹ค์ œ ์‹œ๊ฐ„ ์ดˆ๊ณผ(๊ธด ์š”์ฒญ) ํ›„ gunicorn์ด ์ž‘์—…์ž๋ฅผ ์ฃฝ์ด๊ณ  ์ƒˆ ์ž‘์—…์ž๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€๋งŒ ์ƒˆ ์ž‘์—…์ž๊ฐ€ TIMEOUT ์ œํ•œ ๋‚ด์—์„œ ์‹œ์ž‘ํ•  ์ˆ˜ ์—†๊ณ  ๋ถ€๋ชจ ํ”„๋กœ์„ธ์Šค์— ์•Œ๋ฆด ์œ„์น˜์— ๋„๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ผ์ด๋ธŒ, ๊ทธ๋ž˜์„œ gunicorn์€ ๊ทธ๊ฒƒ์„ ๊ณ„์†ํ•ด์„œ ์ฃฝ์ž…๋‹ˆ๋‹ค :(. ์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ ๋ฌธ์ œ๋Š” Gevent ๋ฐ Sentry์™€ ๊ด€๋ จ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค(https://github.com/getsentry/raven-python/issues/305). Sentry๋Š” ์‹œ์ž‘์—์„œ ๋ฉˆ์ถฅ๋‹ˆ๋‹ค. .
BTW ์ž‘์—…์ž ์‹œ์ž‘ ์‹œ๊ฐ„์— ๋Œ€ํ•ด ๋ณ„๋„์˜ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์žˆ๊ณ  "์‹œ๊ฐ„ ์ดˆ๊ณผ" ์‹œ๊ฐ„ ๋‚ด์— ์‹œ์ž‘ํ•  ์ˆ˜ ์—†๋Š” ์ž‘์—…์ž ๋‚ด ์ผ๋ถ€ ์ถ”๊ฐ€ ๋กœ๊ทธ๊ฐ€ ์žˆ์œผ๋ฉด ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

์‹œ๊ฐ„ ์ดˆ๊ณผ๋Š” ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๊ธด ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ๋‹ค๋ฅธ ์ž‘์—…์ž๋Š” ์—ฌ์ „ํžˆ ์ค‘์žฌ์ž์—๊ฒŒ ํ•˜ํŠธ๋น„ํŠธ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์‹œ๊ฐ„์€ ์‹œ์ž‘ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ์˜๋ฏธ์—์„œ gunicorn์—๋Š” "์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ"๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์˜ˆ, ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋Š” ๋น„๋™๊ธฐ์˜ ์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋น„๋™๊ธฐ "์ปจํ…์ŠคํŠธ ์ „ํ™˜"์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜ ํ˜ธ์ถœ์ด ์—†๋Š” ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ(์˜ˆ: "์†Œ์ผ“ - ์ฝ๊ธฐ/์“ฐ๊ธฐ")์€ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ์˜ ์›์ธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ž‘์—…์ž ์‹œ์ž‘ ์‹œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์š”์ฒญ์ด ์ „ํ˜€ ์—†๋Š” ๊ฒฝ์šฐ). ๊ทธ๋Ÿฌ๋‚˜ Gunicorn ๋กœ๊ทธ์—๋Š” ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ๊ฒฝ์šฐ๋ฅผ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์œผ๋ฉฐ "WORKER TIMEOUT"์ด๋ผ๋Š” ๋ฉ”์‹œ์ง€๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ ์„ค์ •์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹œ์ž‘ ์‹œ๊ฐ„์ด ๊ธด ์•ฑ์ด ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋ฒ”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
1) ์š”์ฒญ ์‹คํ–‰ ์‹œ๊ฐ„ ์ธก์ •์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์š”์ฒญ์ด ๋๋‚  ๋•Œ์™€ ๊ตฌ๊ฑธํ•  ๋•Œ ์‹œ์ฐจ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
2) "์‹คํ–‰ ๋‹จ์œ„"(์ปจํ…์ŠคํŠธ ์ „ํ™˜ ์‚ฌ์ด์—์„œ ์‹คํ–‰๋˜๋Š” ์ฝ”๋“œ์˜ ์–‘)์˜ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์žก๋Š” ๊ฒƒ์€ gevent์—์„œ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด๋–ค ์ œ์•ˆ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ๋ฌธ์ œ๊ฐ€ ํ•ฉ๋ฒ•์ ์ธ ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฐ ์ž ์žฌ์ ์œผ๋กœ ๊ณ„๋‹จ์‹์œผ๋กœ ์ธํ•œ ๊ฒƒ์ผ ๊ฒฝ์šฐ
์ฒ˜์Œ ์‹คํ–‰ํ•  ๋•Œ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ์„œ๋ฒ„ ๋ถ€ํ•˜๋กœ ์ธํ•œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?
์—ฌ๊ธฐ์„œ ํ•  ์ผ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์•„๋‹ˆ๋ฉด ์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ์„ ์ˆ˜ ์žˆ๊ณ  ๋” ์ž˜ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
๋‹ค๋ฅธ ์ˆ˜์ค€์˜ ์ธํ”„๋ผ์—์„œ ์šด์˜?
2014๋…„ 7์›” 30์ผ ์˜คํ›„ 1์‹œ 14๋ถ„์— "Mkrtich" [email protected]์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๋•Œ๋ฌธ์— ๊ทธ๋ ‡๊ฒŒ ์ƒ๊ฐํ•˜์ง€ ๋งˆ์‹ญ์‹œ์˜ค.
1) ์š”์ฒญ ๋Ÿฐํƒ€์ž„ ์ธก์ •์ด ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์‹œ์ฐจ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๊ตฌ๊ฑธํ•˜๊ณ  ์š”์ฒญ์ด ๋๋‚  ๋•Œ.
2) "์‹คํ–‰ ๋‹จ์œ„"(์ฝ”๋“œ์˜ ์–‘)์˜ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์žก๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ปจํ…์ŠคํŠธ ์ „ํ™˜ ์‚ฌ์ด์—์„œ ์‹คํ–‰) gevent์—์„œ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/benoitc/gunicorn/issues/588#issuecomment -50673040.

์ œ์•ˆ์€ 2๊ฐœ์˜ ํƒ€์ž„์•„์›ƒ ๋งค๊ฐœ๋ณ€์ˆ˜์™€ 2๊ฐœ์˜ ๋‹ค๋ฅธ ๋กœ๊ทธ๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
1) ํ•˜๋‚˜๋Š” ์š”์ฒญ ์ฒ˜๋ฆฌ ์ค‘์—๋งŒ ์ž‘๋™ํ•˜๋Š” ํ˜„์žฌ ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋งค๊ฐœ๋ณ€์ˆ˜์ž…๋‹ˆ๋‹ค.
2) ๋‘ ๋ฒˆ์งธ๋Š” ์ž‘์—…์ž ์‹œ์ž‘ ์‹œ๊ฐ„ ์ดˆ๊ณผ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋„ ๋ณด๊ณ 

์šฐ๋ฆฌ๋Š” ๊ฒฐ๊ตญ Heroku์šฉ uWSGI๋กœ ์ „ํ™˜ํ–ˆ๊ณ  ๋” ๋‚˜์€ ์„ฑ๊ณต์„ ๊ฑฐ๋’€์Šต๋‹ˆ๋‹ค... Gunicorn์— ๋Œ€ํ•œ ์ˆ˜์ • ์‚ฌํ•ญ์ด ์•„๋‹Œ ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ์ œ์•ˆ์ด ํ”„๋กœ๋•์…˜ ์„œ๋ฒ„์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ๋‚˜์ค‘์— ํ•ด๊ฒฐ์ด ํ•„์š”ํ•œ ์‚ฌ๋žŒ์—๊ฒŒ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. .

@nebstrebor ์‹œ๊ฐ„ ์ œํ•œ์„ ๋‚ฎ์ถ”๋Š” ์ œ์•ˆ์„ ์‹œ๋„ ํ–ˆ์Šต๋‹ˆ๊นŒ?

@CrazyPython ํ‹ฐ์ผ“์ด ๋งˆ๊ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•˜๋Š” ์ƒˆ ํ‹ฐ์ผ“์„ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋™์ผํ•œ ๋ฌธ์ œ์ธ์ง€, ๋‹ค๋ฅธ ๋ฌธ์ œ์ธ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ํ™•์‹คํžˆ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. :)

์˜ˆ, ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋Œ€๋กœ ์ฐจ์ด๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” ์‚ฐ๋ฐœ์ ์ด์—ˆ๋‹ค
์ถฉ๋ถ„ํžˆ (๊ฒฐ์ฝ” ๋ฒˆ์‹ํ•  ์ˆ˜ ์—†์—ˆ์Œ)
๊ทธ๋ ‡๊ฒŒ ํ•˜์„ธ์š”(1๋…„ ์ด์ƒ ์ง€๋‚ฌ์Šต๋‹ˆ๋‹ค). ๋‚˜๋Š” Gunicorn์„ ์ •๋ง ์ข‹์•„ํ•˜์ง€๋งŒ,
๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ๋Š” ๋ฌธ์ œ ์—†์ด Heroku ์™ธ๋ถ€์—์„œ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ฒค ๋กœ๋ฒ„์ธ 
CTO ๋ฐ ๊ณต๋™ ์„ค๋ฆฝ์ž
์ฃผ์‹ํšŒ์‚ฌ ๋‰ดํŠธ๋ฆฌ์Šฌ๋ผ์ด์Šค
[email protected]
์…€ - 801-735-7845

2015๋…„ 6์›” 30์ผ ํ™”์š”์ผ ์˜ค์ „ 8:08 Benoit Chesneau [email protected]
์ผ๋‹ค:

@nebstrebor https://github.com/nebstrebor ์ž˜ ํ•ด๋ณด์…จ๋‚˜์š”?
์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋‚ฎ์ถ”๋Š” ์ œ์•ˆ?

@CrazyPython https://github.com/CrazyPython ํ‹ฐ์ผ“์ด ๋งˆ๊ฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
์ƒˆ ํ‹ฐ์ผ“์„ ์—ด ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฌธ์ œ๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
์žฌ์ƒ์‚ฐ? ๊ฐ™์€ ๋ฌธ์ œ์ธ์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ํ™•์‹คํžˆ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋‹ค๋ฅธ ๊ฒƒ๊ณผ ๊ณต๋™ :)

โ€”
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ฑฐ๋‚˜ GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/benoitc/gunicorn/issues/588#issuecomment -117199606.

์šฐ๋ฆฌ๋„ ์ด ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‘ ์ž‘์—…์ž(--workers 2) ๋ชจ๋‘ ์žฅ๊ธฐ ์‹คํ–‰ ์š”์ฒญ์— ์ „ํ™”๋ฅผ ๋Š๊ณ  ๊ฒฐ๊ตญ ์ฃฝ๊ณ (--timeout 20) ์ฆ‰์‹œ ๋‘ ๊ฐœ์˜ H13์ด ํ‘œ์‹œ๋˜๊ณ  H12 ๋ฐ WORKER TIMEOUT์ด ๋‹ค์‹œ ์‹œ์ž‘๋˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ 10๋ถ„ ๋™์•ˆ ๊ณ„์†ํ•ด์„œ ์ž‘์—…์ž๋Š” ์ œํ•œ ์‹œ๊ฐ„์— ๋„๋‹ฌํ•˜๊ณ  ๋‹ค์‹œ ์‹œ์ž‘๋˜๊ธฐ ์ „์— ์š”์ฒญ์„ ์„ฑ๊ณต์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” dyno๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘ํ–ˆ๊ณ  ๊ณ ์ณค์Šต๋‹ˆ๋‹ค.

ํ•œ ๊ฐ€์ง€ ํฅ๋ฏธ๋กœ์šด ์ ์€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์–ธ๊ธ‰ํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ๋‘ ๊ฐœ์˜ H13(์‘๋‹ต ์—†์ด ์—ฐ๊ฒฐ์ด ๋‹ซํž˜)์„ ๋ณด๊ณ  ๋งˆ์นจ๋‚ด SIGTERM์„ ๋ฐœํ–‰ํ–ˆ์„ ๋•Œ H13 - 48์˜ ํ™์ˆ˜๋ฅผ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ •ํ™•ํžˆ ๋งํ•˜๋ฉด ์šฐ๋ฆฌ๊ฐ€ ๋ณธ ๊ฒƒ๊ณผ ๋™์ผํ•œ ์ˆ˜์˜ WORKER TIMEOUT์ž…๋‹ˆ๋‹ค(์ฆ‰๊ฐ์ ์ธ H13์„ ๋ณธ ์ฒ˜์Œ ๋‘ ๊ฐœ ์ œ์™ธ). ์ •ํ™•ํžˆ ๋ฌด์Šจ ๋œป์ธ์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ์˜์‹ฌ์Šค๋Ÿฝ๋„ค์š”....

H13s ๋˜๋Š” H12s๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ด๊ฑฐ ํ—ค๋กœ์ฟ ์—์„œ ๋‚˜์˜จ๊ฑด๊ฐ€์š”? gunicorn์ด ๋ฌถ์ผ ํฌํŠธ๋Š” ์–ด๋–ป๊ฒŒ ์ œ๊ณต๋ฉ๋‹ˆ๊นŒ? heroku ํ”„๋ก์‹œ๊ฐ€ ์†Œ์ผ“์ด ๋‹ซํžŒ ๊ฒƒ์„ ๊ฐ์ง€ํ•˜์ง€ ๋ชปํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์–ด๋–ค ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

์˜ˆ, Heroku ์˜ค๋ฅ˜ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.
H12 - ์š”์ฒญ ์‹œ๊ฐ„ ์ดˆ๊ณผ - ์ผ๋ฐ˜์ ์œผ๋กœ 30์ดˆ(https://devcenter.heroku.com/articles/error-codes#h12-request-timeout)
H13 - ์‘๋‹ต ์—†์ด ์—ฐ๊ฒฐ ์ข…๋ฃŒ - (https://devcenter.heroku.com/articles/error-codes#h13-connection-closed-without-response)

ํŽธ์ง‘ : ๋‚˜๋Š” gunicorn์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ PORT๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์œผ๋ฏ€๋กœ ํฌํŠธ๊ฐ€ ๊ตฌ์„ฑ๋œ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

๋™๊ธฐ ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์–ธ๊ธ‰ํ•˜๋Š” ๊ฒƒ์„ ์žŠ์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” gunicorn 19.3.0์„ ์‹คํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค.

์˜ค๋žซ๋™์•ˆ ํ™œ๋™์ด ์—†์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๋ฅผ ๋‹ซ์Šต๋‹ˆ๋‹ค. ์ง€์—ฐ๋œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์žˆ์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜ค๋ž˜ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํ‹ฐ์ผ“์—์„œ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ—ค์ด ๋‚˜๋Š” ๋˜ํ•œ ์ƒˆ๋กœ์šด ์œ ๋ฌผ ๊ด€๋ฆฌ์ž procfile์„ ์‚ฌ์šฉํ•˜์—ฌ heroku์˜ gunicorn uvicorn๊ณผ ๋™์ผํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

newrelic-admin run-program gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:fastapi_app -b 0.0.0.0:${PORT:-5000} --log-level info --access-logfile=- --logger-class=gunicorn_color.Logger --preload

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์‹œ์Šคํ…œ์ด ๋ถ€ํŒ…๋˜์ž๋งˆ์ž ์ด ๋กœ๊ทธ๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

2021-03-19T13:18:19.187532+00:00 heroku[web.1]: State changed from starting to up
2021-03-19T13:18:51.964740+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/" host=api-app-clienti-pr-49.herokuapp.com request_id=8742009a-3e56-4f83-a147-97ff84d4e30b fwd="5.89.111.249" dyno=web.1 connect=1ms service=30003ms status=503 bytes=0 protocol=https
2021-03-19T13:19:04.292784+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/api" host=api-app-clienti-pr-49.herokuapp.com request_id=85b6320a-7728-4074-87eb-b0992e7c3f9d fwd="5.89.111.249" dyno=web.1 connect=3ms service=30001ms status=503 bytes=0 protocol=https
์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰