Gunicorn: Gunicorn ๋™๊ธฐํ™” ์ž‘์—…์ž๊ฐ€ docker + AWS์—์„œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋จ

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

AWS์˜ Ubuntu 14.04 LTS์—์„œ ์‹คํ–‰๋˜๋Š” ๋„์ปค ์ด๋ฏธ์ง€ ๋‚ด์—์„œ gunicorn 19.4.5๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด >1 ๋™๊ธฐํ™” ์ž‘์—…์ž์™€ ๊ธฐ๋ณธ 30์ดˆ ์ œํ•œ ์‹œ๊ฐ„์œผ๋กœ ์‹คํ–‰ํ•  ๋•Œ ์ž‘์—…์ž ์ œํ•œ ์‹œ๊ฐ„์ด ๊ณ„์† ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ #588 ๋˜๋Š” #942์™€ ๊ด€๋ จ์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์ด๊ฒƒ์€ ์ƒ๋‹นํžˆ ์ตœ์‹  ๋ฒ„์ „์˜ gunicorn์ด๋ฏ€๋กœ ํ™•์‹คํ•˜๊ฒŒ ๋งํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์—ฌ๋Ÿฌ ์‹คํ–‰์— ๋Œ€ํ•œ ์ •ํ™ฉ ์ฆ๊ฑฐ์— ๋”ฐ๋ฅด๋ฉด ์ž‘์—…์ž ์ค‘ ํ•œ ๋ช…์ด ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š์•˜์œผ๋ฉฐ ๊ณ„์† ์‹คํŒจํ•˜๊ณ  ๋‹ค์‹œ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์€ N-1๋ช…์˜ ๋‚˜๋จธ์ง€ ์ž‘์—…์ž๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚˜๋Š” ์ด๊ฒƒ์„ ์ œ์•ˆํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ๋งŒ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์œผ๋ฏ€๋กœ ์ด๋ฅผ ๊ฐ•๋ ฅํ•œ ์‹ ํ˜ธ๋กœ ๋ฐ›์•„๋“ค์ด์ง€ ๋งˆ์‹ญ์‹œ์˜ค.

์ œ๊ฐ€ ํ™•์ธํ•œ ์‚ฌํ•ญ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ๋ฌธ์ œ๊ฐ€ ๋„์ปค ์™ธ๋ถ€์—์„œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ๋™์ผํ•œ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•˜์ง€๋งŒ AWS์—์„œ๋Š” ๋ฐœ์ƒํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?
    ์•„๋‹ˆ์š”, AWS์˜ docker์—์„œ๋งŒ ๋ฌธ์ œ๋ฅผ ๋ณต์ œํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐ 30์ดˆ ์ด์ƒ ๊ฑธ๋ฆฌ๋‚˜์š”?
    ์•„๋‹ˆ์š”, ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ 1์ดˆ ์ด๋‚ด์— ์ดˆ๊ธฐํ™”๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
  • ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด ์ค‘๋‹จ๋˜๋Š” ์š”์ฒญ์„ ์ˆ˜์‹ ํ•ฉ๋‹ˆ๊นŒ?
    ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋Œ€ํ•œ ์š”์ฒญ ์—†์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์— gunicorn์„ ํ˜ผ๋™์‹œํ‚ค๋Š” ์†์ƒ๋œ ์ดˆ๊ธฐํ™” ์ฝ”๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?
    ๋™์ผํ•œ ๊ตฌ์„ฑ(>1 ๋™๊ธฐํ™” ์ž‘์—…์ž ํฌํ•จ)์—์„œ gunicorn์„ ์‹คํ–‰ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์ง€๋งŒ ๋‹ค๋ฅธ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ƒˆ๋กœ์šด ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์€ gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ gunicorn์—์„œ ๋ฌธ์ œ ์—†์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
  • ๋„์ปค์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์ด ctime์„ ์—…๋ฐ์ดํŠธํ•˜์ง€ ๋ชปํ•ฉ๋‹ˆ๊นŒ?
    ์•„๋ž˜ ๋กœ๊ทธ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค -- ctime์€ ์ผ๋ฐ˜์ ์œผ๋กœ ์ž˜ ์ง„ํ–‰๋˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. Docker์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์€ ์‚ญ์ œ๋œ ํŒŒ์ผ์— stat -L ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ gunicorn์ด ํŒŒ์ผ ์—ฐ๊ฒฐ์„ ํ•ด์ œํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๋ฉด stat -L ์—์„œ ctime์ด ํ‰์†Œ์™€ ๊ฐ™์ด ์—…๋ฐ์ดํŠธ๋˜๊ณ  ์žˆ์Œ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

workertmp.py ์— ๋ช‡ ๊ฐ€์ง€ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๊ฐ ๊ฒ€์‚ฌ์—์„œ ์ฝ์€ ctime์„ ๊ธฐ๋กํ–ˆ์œผ๋ฉฐ ๋‹ค์Œ์€ ๊ทธ๋Ÿฌํ•œ ๋กœ๊ทธ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค(๋ชจ๋“  ์ž‘์—…์ž ๊ฐ„์— ์ธํ„ฐ๋ฆฌ๋ธŒ๋จ).

[2016-01-29 00:21:38 +0000] [3238] [INFO] Starting gunicorn 19.4.0
[2016-01-29 00:21:38 +0000] [3238] [INFO] Listening at: http://0.0.0.0:5000 (3238)
[2016-01-29 00:21:38 +0000] [3238] [INFO] Using worker: sync
[2016-01-29 00:21:38 +0000] [3243] [INFO] Booting worker with pid: 3243
[2016-01-29 00:21:38 +0000] [3244] [INFO] Booting worker with pid: 3244
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026899.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026900.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026899.03
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026905.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026904.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026910.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026909.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026914.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026933.73
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026934.74
FOOBAR: modify /tmp/wgun[2016-01-29 00:22:25 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00:22:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-01-29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 3330
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunic54026934.74
FOOBAR: modify /tmp/wgun[2016-01-29 00:22:25 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00:22:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-01-29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 3330
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time:fy] [3238] [CRITICAL] WORKER TIMEOUT (pid:3243)
[2016-01-29 00p/2:25 +0000] [3243] [INFO] Worker exiting (pid: 3243)
[2016-0ic29 00:22:25 +0000] [3330] [INFO] Booting worker with pid: 33myicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorntiyjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt45ime: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026945.82
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026946.01
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8corn-myjLwI time:fy] [3238] [CRITICAL] WORKER TIMEOUT (pid:32BA)
[2016-01-29 00p/2:25 +0000] [3243] [INFO] Worker exiting (pdify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
FOOBAR: modify /tmp/wgunicorn-Mw64T1 timeodify /tmp/wgunicorn-myjLwI time: 1454026964.74
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026969.74
FOO[2016-01-29 00:22:59 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3330)
[2016-01-29 00:22:59 +0000] [3330] [INFO] Worker exiting (pid: 3330)
icorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026935.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026939.74
FOOBAR: modify /tmp/wgunicorn-LwI time: 1454026965.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 tI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026940.0
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026944.74
FOOBAR: modify /tmp/wgunicorn-RhAFmt time: 1454026915.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.0
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026945.8
[2016-01-29 00:22:59 +0000] [3396] [INFO] Booting worker with pid: 3396
BAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
FOOBAR: modify /tmp/wgunicorn-myjL26949.74
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
FOOBAR: modify /tmp/w79.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026979.97
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
80.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454029.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026979.95
FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 WORKER TIMEOUT (pid:3396)
 [2016-01-29 00:23:31 +0000] [3396] [INFO] Worker exiting (pid: 3396)
 BAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026970.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026974.74
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw64T1 time: 1454026949.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454026975.0
 FOOBAR: modify /tmp/wgunicorn-Mw6nicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027005.0
 FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027010.0
 FOOBAR: modify /tmp/wgunicorn-k3uZLy time: 1454026980.16
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027010.0
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.08
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027011.28
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmprn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-Znicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027011.06
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027028.98
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wguicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027030.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn--ZmVaVS time: 1454027014.74
 FOOBAR: modify /tmp/wgunicorn-myjLwI time: 1454027035.0
 FOOBAR: modify /tmp/wgunicorn-ZmVaVS time: 1454027014.74
 FOOBAR: modify /t[2016-01-29 00:24:05 +0000] [3238] [CRITICAL] WORKER TIMEOUT (pid:3453)
 [2016-01-29 00:24:05 +0000] [3453] [INFO] Worker exiting (pid: 3453)
FeaturIPC PlatforDocker - Bugs -

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋Œ€์‹  gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

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

hrmmm ์œ„์˜ ๋กœ๊ทธ์—์„œ ์‹œ๊ฐ„์ด ์ ˆ๋Œ€ ๋ณ€ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

์ด ๋ฒ„๊ทธ์˜ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

AWS(Elastic Beanstalk + EC2 Container Service)์˜ Docker ์ด๋ฏธ์ง€ ๋‚ด์—์„œ gunicorn์„ ์‹คํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ดˆ๊ธฐํ™” ์งํ›„์™€ AWS์—์„œ Docker ์ด๋ฏธ์ง€๋ฅผ ์‹คํ–‰ํ•  ๋•Œ๋งŒ ๋ฐœ์ƒํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๋Š” ์ง€์†์ ์ธ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
๋™์ผํ•œ HTTP ์š”์ฒญ์€ ๋•Œ๋กœ๋Š” ๋ช‡ ms, ๋•Œ๋กœ๋Š” 20-30์ดˆ๊ฐ€ ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ์กด์žฌํ•˜์ง€ ์•Š๋Š” ํŽ˜์ด์ง€, ์ธ์ฆ๋˜์ง€ ์•Š์€ ๋‹จ์ˆœํ•œ "Hello world" ๋ฌธ์ž์—ด ํŽ˜์ด์ง€ ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๋ ˆ์ฝ”๋“œ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ํŽ˜์ด์ง€์ธ์ง€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ถ”๊ฐ€ ์„ธ๋ถ€์ •๋ณด :

  • Gunicorn ๋ฒ„์ „ : 19.5.0 ๋ฐ 19.6.0.
  • ๊ธฐ๋ณธ Docker ์ด๋ฏธ์ง€ : python:3.4 ( OS : Debian Jessie )
  • Docker ๋ฒ„์ „ : 1.9.1(Amazon ECS์—์„œ ๊ด€๋ฆฌ), OS : Amazon Linux AMI 2016.03(Amazon EB์—์„œ ๊ด€๋ฆฌ).
  • ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ”„๋ ˆ์ž„์›Œํฌ : Django ๋ฒ„์ „ 1.9.6 ๋ฐ 1.9.7.

์˜ํ–ฅ์„ ๋ฐ›์ง€ _์•Š์€_

  • ๋กœ์ปฌ ๋จธ์‹  , _inside_ ๋ฐ _outside_ ๋ชจ๋‘ Docker ์ปจํ…Œ์ด๋„ˆ์ž…๋‹ˆ๋‹ค. OS : ์šฐ๋ถ„ํˆฌ 16.04 LTS, ๋„์ปค : 1.11.2.
  • ํ—ค๋กœ์ฟ  ( OS : ์šฐ๋ถ„ํˆฌ 14.04 LTS)

Amazon ์ปจํ…Œ์ด๋„ˆ ๋กœ๊ทธ :

[2016-06-15 16:46:15 +0000] [1] [DEBUG] Current configuration:
  cert_reqs: 0
  post_request: <function PostRequest.post_request at 0x7fb13e187c80>
  worker_connections: 1000
  tmp_upload_dir: None
  enable_stdio_inheritance: False
  timeout: 30
  pre_fork: <function Prefork.pre_fork at 0x7fb13e1871e0>
  worker_int: <function WorkerInt.worker_int at 0x7fb13e1876a8>
  backlog: 2048
  max_requests: 0
  max_requests_jitter: 0
  access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
  logconfig: None
  syslog_addr: udp://localhost:514
  preload_app: False
  pidfile: None
  umask: 0
  secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
  paste: None
  proxy_protocol: False
  worker_class: sync
  on_starting: <function OnStarting.on_starting at 0x7fb13e414c80>
  worker_abort: <function WorkerAbort.worker_abort at 0x7fb13e187840>
  worker_exit: <function WorkerExit.worker_exit at 0x7fb13e187e18>
  config: config/gunicorn.py
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7fb13e18a048>
  daemon: False
  accesslog: None
  errorlog: -
  loglevel: debug
  syslog_prefix: None
  ssl_version: 3
  suppress_ragged_eofs: True
  limit_request_field_size: 8190
  reload: False
  logger_class: gunicorn.glogging.Logger
  statsd_host: None
  keyfile: None
  raw_env: []
  threads: 1
  django_settings: None
  proc_name: None
  proxy_allow_ips: ['127.0.0.1']
  limit_request_fields: 100
  ciphers: TLSv1
  check_config: False
  do_handshake_on_connect: False
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7fb13e187510>
  graceful_timeout: 30
  worker_tmp_dir: None
  certfile: None
  sendfile: None
  keepalive: 2
  chdir: /app/testapp
  when_ready: <function WhenReady.when_ready at 0x7fb13e187048>
  ca_certs: None
  on_exit: <function OnExit.on_exit at 0x7fb13e18a1e0>
  spew: False
  bind: [':8000']
  post_fork: <function Postfork.post_fork at 0x7fb13e187378>
  limit_request_line: 4094
  syslog_facility: user
  workers: 3
  syslog: False
  pre_request: <function PreRequest.pre_request at 0x7fb13e187b70>
  user: 0
  group: 0
  forwarded_allow_ips: ['127.0.0.1']
  pythonpath: None
  on_reload: <function OnReload.on_reload at 0x7fb13e414e18>
  pre_exec: <function PreExec.pre_exec at 0x7fb13e1879d8>
  default_proc_name: config.wsgi
  statsd_prefix: 
[2016-06-15 16:46:15 +0000] [1] [INFO] Starting gunicorn 19.5.0
[2016-06-15 16:46:15 +0000] [1] [DEBUG] Arbiter booted
[2016-06-15 16:46:15 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2016-06-15 16:46:15 +0000] [1] [INFO] Using worker: sync
[2016-06-15 16:46:15 +0000] [8] [INFO] Booting worker with pid: 8
[2016-06-15 16:46:15 +0000] [9] [INFO] Booting worker with pid: 9
[2016-06-15 16:46:15 +0000] [10] [INFO] Booting worker with pid: 10
[2016-06-15 16:46:15 +0000] [1] [DEBUG] 3 workers
[2016-06-15 16:46:52 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2016-06-15 16:46:52 +0000] [9] [INFO] Worker exiting (pid: 9)
[2016-06-15 16:46:52 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:10)
[2016-06-15 16:46:52 +0000] [10] [INFO] Worker exiting (pid: 10)
[2016-06-15 16:46:53 +0000] [20] [INFO] Booting worker with pid: 20
[2016-06-15 16:46:53 +0000] [1] [DEBUG] 2 workers
[2016-06-15 16:46:53 +0000] [21] [INFO] Booting worker with pid: 21
[2016-06-15 16:46:53 +0000] [1] [DEBUG] 3 workers
[2016-06-15 16:47:23 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:8)
(...)

`

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

์ €๋„ ์ด๊ฑฐ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์˜์‹ฌ์€ Elastic Load Balancer์ž…๋‹ˆ๋‹ค. ์ด์ „ ํšŒ์‚ฌ์—์„œ paste ๋ฅผ ์‚ฌ์šฉํ–ˆ๋Š”๋ฐ ์ด๋กœ ์ธํ•ด ELB์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒ ๋“  ์—ฐ๊ฒฐ์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ  paste ์—์„œ ๋”ธ๊พน์งˆ์„ ์ผ์œผํ‚ค๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” ์ด์ œ gunicorn์„ ์‚ฌ์šฉํ•˜๋Š” ์ƒˆ ์ง์žฅ์— ์žˆ์œผ๋ฉฐ ELB ๋’ค์— ์„œ๋ฒ„๋ฅผ ๋ฐฐ์น˜ํ•˜๊ธฐ ์‹œ์ž‘ํ•  ๋•Œ๊นŒ์ง€ ๋ชจ๋“  ๊ฒƒ์ด ๊ดœ์ฐฎ์•˜์Šต๋‹ˆ๋‹ค.

๋Œ€์‹  gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ ‡๋‹ค๋ฉด ์ด๊ฒƒ์ด ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•˜๊ณ  ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ๋ฌถ๋Š” ELB์˜ ๋ฌธ์ œ์ž…๋‹ˆ๊นŒ? ์šฐ๋ฆฌ๊ฐ€ ์˜๋„์ ์œผ๋กœ ๋™๊ธฐํ™” ์ž‘์—…์ž์™€์˜ ์—ฐ๊ฒฐ์„ ๋‹ซ์•„์•ผ ํ•œ๋‹ค๊ณ  ์‹ ํ˜ธ๋ฅผ ๋ณด๋‚ด๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ์ด์ƒํ•˜๊ฒŒ ๋Š๊ปด์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค. https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L168

ํ•˜์ง€๋งŒ ์˜๋„์ ์œผ๋กœ ์—ฐ๊ฒฐ์„ ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. client.close() ํ˜ธ์ถœ์„ ๋ฌด์กฐ๊ฑด์ ์œผ๋กœ ์ด๋™ํ•˜๋Š” ํ…Œ์ŠคํŠธ๋ฅผ ์›ํ•˜๋Š” ์‚ฌ๋žŒ์ด ์žˆ๋‹ค๋ฉด ํฅ๋ฏธ๋กœ์šด ํ…Œ์ŠคํŠธ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/sync.py#L199

ELB์˜ ์œ ํœด ์‹œ๊ฐ„ ์ดˆ๊ณผ๊ฐ€ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ณด๋‹ค ๋‚ฎ์€์ง€ ํ™•์ธํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋ฌธ์ œ์˜ ์›์ธ์ธ์ง€๋„ ์‹ ์†ํ•˜๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. http://docs.aws.amazon.com/elasticloadbalancing/latest/ ํด๋ž˜์‹/config-idle-timeout.html

@tilgovi elb๋Š” ํ˜„์žฌ ์ตœ์„ ์˜ ์ถ”์ธก์ž…๋‹ˆ๋‹ค. a) gunicorn์ด ELB ๋’ค์— ์žˆ๊ณ  b) gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๊ฐ€ ์ˆ˜์ •๋œ ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทผ๋ฐ ๋˜ ๋ˆ„๊ฐ€์•Œ์•„..

ELB ๋’ค์—์„œ๋งŒ ๋ฐœ์ƒํ•˜๋ฉฐ ํ”„๋กœํ† ์ฝœ HTTP ๋˜๋Š” HTTPS๊ฐ€ ELB์— ์„ค์ •๋œ ๊ฒฝ์šฐ์—๋งŒ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
ํ”„๋กœํ† ์ฝœ์„ TCP ๋˜๋Š” SSL๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.
์•„์ง ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•„๋Š” ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์•ก์„ธ์Šค ๋กœ๊ทธ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๊ณ  ELB์˜ HTTP/HTTPS์— ๋Œ€ํ•ด์„œ๋งŒ ํ™œ์„ฑํ™”๋œ X-Forwarded-For ํ—ค๋”๋ฅผ ๋ณผ ๋•Œ ์ง€๊ธˆ๊นŒ์ง€ ์„ค๋ช…ํ•œ ์ˆ˜์ • ์‚ฌํ•ญ(HTTP ๋Œ€์‹  TCP)์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. :)

์ด์ƒํ•˜๊ฒŒ๋„, ์šฐ๋ฆฌ๊ฐ€ ๊ฐ™์€ ํŽ˜์ด์ง€์— ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ELB์—์„œ HTTP/HTTPS ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ๋•Œ ์ผ์ข…์˜ ์ตœ์ ํ™”๊ฐ€ ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๊นŒ? ์ด ์ตœ์ ํ™”๋กœ ์ธํ•ด ๋™๊ธฐํ™” ์ž‘์—…์ž์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๊นŒ?

@ecs HTTP/HTTPS ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๊ฐ€ ๋™์ผํ•œ TCP ์—ฐ๊ฒฐ์„ ์žฌ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ELB๊ฐ€ ์˜ค๋žซ๋™์•ˆ

Btw, ์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋Š” ๋งŽ์€ ์š”์ธ(gunicorn ๋ฒ„์ „, ์ž‘์—…์ž ํด๋ž˜์Šค, ๋‚ด๋ถ€ ๋„์ปค ์—ฌ๋ถ€, ELB ํ”„๋กœํ† ์ฝœ)์ด ์žˆ์œผ๋ฏ€๋กœ ๋ˆ„๊ตฐ๊ฐ€ ELB์˜ TCP ํ”„๋กœํ† ์ฝœ์ด HTTP์™€ ๋‹ฌ๋ฆฌ ์ž‘๋™ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธํ•˜๊ณ  ํ™•์ธํ•˜๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. Ubuntu 14.04 ๋ฐ gunicorn ๋ฒ„์ „ 19.3.0์—์„œ ํ˜ธ์ŠคํŒ…๋˜๋Š” ๋„์ปค์—์„œ ํ…Œ์ŠคํŠธ ์ค‘์ž…๋‹ˆ๋‹ค.

๋‚˜๋„ ๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ์•ˆ๊ณ ์žˆ์–ด:
[2016-10-03 12:13:17 +0000] [6] [CRITICAL] ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ(pid:16)
[2016-10-03 12:13:17 +0000] [16] [INFO] ์ž‘์—…์ž ์ข…๋ฃŒ (pid: 16)
[2016-10-03 12:13:17 +0000] [6] [CRITICAL] ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ(pid:20)
[2016-10-03 12:13:17 +0000] [20] [INFO] ์ž‘์—…์ž ์ข…๋ฃŒ (pid: 20)
[2016-10-03 12:13:17 +0000] [33] [INFO] pid๋กœ ์ž‘์—…์ž ๋ถ€ํŒ…: 33

๋‚ด ์„ค์ •.

kube-aws๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AWS์—์„œ core-os๊ฐ€ ์žˆ๋Š” kubernetes ํด๋Ÿฌ์Šคํ„ฐ๋ฅผ ์„ค์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/coreos/coreos-kubernetes/tree/master/multi-node/aws

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

์šฐ๋ฆฌ๋Š” ํ˜„์žฌ ์ด ๋ฌธ์ œ๋ฅผ ๋ณด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐํšŒ๊ฐ€ ์žˆ์„ ๋•Œ ๋” ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๊ฒŒ์‹œํ•˜๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. gevent๋กœ ์ด๋™ํ•˜๋ฉด ์‹ค์ œ๋กœ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋ฏ€๋กœ ๋™๊ธฐํ™” ์ž‘์—…์ž์™€ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ECS ๋ฐ ELB๊ฐ€ ์žˆ๋Š” AWS์— ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ ์•ฑ ์ค‘ ํ•˜๋‚˜์—์„œ๋„ ๋™์ผํ•œ ์ด์ƒํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฆฌ์Šค๋„ˆ๋ฅผ HTTP์—์„œ tcp๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์‹ค์ œ๋กœ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค.

๋ˆ„๊ตฌ๋“ ์ง€ ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๋Š” ๋‹จ๊ณ„๋ณ„ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? (๊ตฌ์„ฑ ๋‹จ๊ณ„ ๋“ฑ) ๋˜๋Š” ์ตœ์†Œํ•œ ํ•ด๋‹น ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ฃผ์„ธ์š”. ์ด๋ฒˆ ์ฃผ์— ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฐธ๋Ÿฐ์„œ์— ๋Œ€ํ•ด HTTP์— ์˜์กดํ•˜๋ ค๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ์—ฐ๊ฒฐ ์œ ์ง€(tcp ์ œ์™ธ)๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ๋™๊ธฐํ™” ์ž‘์—…์ž๊ฐ€ ์ง€์›์„ ์œ„ํ•ด ์—…๋ฐ์ดํŠธ๋  ๋•Œ๊นŒ์ง€ ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์ด ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

๊ธฐ๋ณธ Flask ์•ฑ์„ โ€‹โ€‹์„ค์ •ํ•˜๊ณ  HTTP ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ๋ฐ ์œ„์˜ ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ AWS์˜ docker ๋‚ด๋ถ€์—์„œ ๋™๊ธฐํ™” ์ž‘์—…์ž์™€ ํ•จ๊ป˜ gunicorn์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

AWS์˜ Ubuntu 14.04 LTS์—์„œ ์‹คํ–‰๋˜๋Š” ๋„์ปค ์ด๋ฏธ์ง€ ๋‚ด์—์„œ gunicorn 19.4.5๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด >1 ๋™๊ธฐํ™” ์ž‘์—…์ž์™€ ๊ธฐ๋ณธ 30์ดˆ ์ œํ•œ ์‹œ๊ฐ„์œผ๋กœ ์‹คํ–‰ํ•  ๋•Œ ์ž‘์—…์ž ์ œํ•œ ์‹œ๊ฐ„์ด ๊ณ„์† ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

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

  • ์ด ๋™์ž‘๊ณผ ์ด๋ฅผ ์žฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ณธ ์ ‘๊ทผ ๋ฐฉ์‹์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ๋™์ž‘์€ Docker์— ๊ตญํ•œ๋˜์ง€ ์•Š๊ณ  ๋™๊ธฐํ™” ์ž‘์—…์ž/keepalive ์„ค์ •์— ๊ตญํ•œ๋˜๋ฏ€๋กœ ์ œ๋ชฉ ๋ณ€๊ฒฝ์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค...

  • ์—ฌ๊ธฐ์— ์„ค๋ช…๋œ ๋‚ด์šฉ์„ ๋”ฐ๋ฅด๋„๋ก keepalive ์„ค์ •์„ ์ˆ˜์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ (๊ฐ€์žฅ ํฅ๋ฏธ๋กœ์šด ๋ถ€๋ถ„์€ ์ธ์šฉ๋ฌธ์ž…๋‹ˆ๋‹ค. AWS ELB ์„ค๋ช…์„œ์—์„œ) ์„œ๋ฒ„๊ฐ€ ๋” ์ด์ƒ ์ด ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ด์ง€ ์•Š๋Š” ๊ฒƒ์œผ๋กœ ๋‚˜ํƒ€๋‚ฌ์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ์ถ”๊ฐ€๋กœ gthread ์ž‘์—…์ž ํด๋ž˜์Šค๋กœ ๋ณ€๊ฒฝํ–ˆ์œผ๋ฉฐ ๊ฒฐ๊ณผ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๋งค์šฐ ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ 65์ดˆ ์ œํ•œ ์‹œ๊ฐ„(AWS ELB ์ œํ•œ ์‹œ๊ฐ„์€ 60์ดˆ, AFAIK)์œผ๋กœ gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์— 1๊ฐœ์˜ ์š”์ฒญ์ด ์ „์†ก๋˜๋Š” ํ•œ ํด๋ผ์ด์–ธํŠธ๋งŒ ์š”์ฒญ์„ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋„ ์—ฌ์ „ํžˆ 504 ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์ง€๋งŒ ์•„์ง๊นŒ์ง€๋Š” ์ด์œ ๋ฅผ ๋ฐํž ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

@obi1kenobi ELB ์‹œ๊ฐ„ ์ดˆ๊ณผ ์˜ต์…˜ ์ด์ƒ์œผ๋กœ keepalive๋ฅผ

@lenucksi keepalive๋Š” ์ด๋ฏธ ELB ์ œํ•œ ์‹œ๊ฐ„๋ณด๋‹ค 5์ดˆ ๋” ๋†’์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„์˜ ์‹œ๊ณ„๊ฐ€ ๊ทธ๋ ‡๊ฒŒ ๋งŽ์ด ๊ตฌ๋™๋˜์ง€ ์•Š๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. :)

์ €๋„ ELB ๋’ค์˜ EC2 ์ธ์Šคํ„ด์Šค์˜ Docker ์ปจํ…Œ์ด๋„ˆ ๋‚ด์—์„œ gunicorn 19.6์„ ์‹คํ–‰ํ•˜๋Š” ์ด ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค(EC2 ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์—ญ๋ฐฉํ–ฅ ํ”„๋ก์‹œ๋ฅผ ์œ„ํ•œ ๊ธฐ๋ณธ HTTP ํ”„๋กœํ† ์ฝœ ์‚ฌ์šฉ).

์•ž์„œ ์ œ์•ˆํ•œ ๋Œ€๋กœ ์ž‘์—…์ž ํด๋ž˜์Šค๋ฅผ gevent๋กœ ์„ค์ •ํ•˜๋ฉด ์ด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค(์ด์ „์—๋Š” ๊ธฐ๋ณธ sync ์ž‘์—…์ž ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ–ˆ์Œ).

๋‚˜๋Š” ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์†Œํ•œ์˜ ์˜ˆ๋ฅผ ์‹œ๋„ํ•˜๊ณ  ๋ฌธ์„œํ™”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ๋ง์„ ๋’ท๋ฐ›์นจํ•˜๊ธฐ ์œ„ํ•ด ELB๋Š” EC2 ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์—ฐ๊ฒฐ์„ ์—ด๊ณ  ์ถ”๊ฐ€ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ๋ชปํ•˜๋„๋ก gunicorn์„ ์ž ๊ทธ๋Š” ๋ฐฉ์‹์œผ๋กœ ์—ด๋ ค ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.

Gunicorn์ด ELB์˜ ์š”์ฒญ ์‹œ๊ฐ„์„ ์ดˆ๊ณผํ•˜์—ฌ ์—ฐ๊ฒฐ์ด ๋ณด๋ฅ˜๋˜์–ด ์ข…๋ฃŒ๋˜๋ฉด ๊ทธ ๋’ค์— ๋Œ€๊ธฐ ์ค‘์ธ ๋ชจ๋“  ๋ณด๋ฅ˜ ์ค‘์ธ ์š”์ฒญ๋„ ์‹คํŒจํ•ฉ๋‹ˆ๋‹ค(ELB์˜ ์ƒํƒœ ํ™•์ธ์„ ํฌํ•จํ•˜์—ฌ ์ธ์Šคํ„ด์Šค๊ฐ€ ELB์—์„œ ์ œ๊ฑฐ๋˜์–ด ๋””๋ฒ„๊ทธํ•˜๊ธฐ๊ฐ€ ๋” ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ) ).

์ด ์ฆ์ƒ์€ Docker์™€ ๊ด€๋ จ์ด ์—†๋Š” ์ด ์ด์ „ ๋ฌธ์ œ์—์„œ ๊ด€์ฐฐ๋œ ๊ฒƒ๊ณผ ์ค‘๋ณต๋จ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. https://github.com/benoitc/gunicorn/issues/588

@jelis ์ด๊ฒƒ์ด ์ผ๋ถ€ kubernetes ๊ตฌ์„ฑ๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๊นŒ?

๋˜ํ•œ SSL ์ข…๋ฃŒ๊ฐ€ ์žˆ๋Š” ELB์— ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ๋กœ๊ทธ์— ๋‹ค์Œ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

[017-03-01 07:36:32 +0000] [1249] [DEBUG] GET /healthcheck
[01/Mar/2017:07:36:32 +0000] "GET /healthcheck HTTP/1.1" 200 22 "-" "ELB-HealthChecker/1.0"
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1203)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1225)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1234)
[017-03-01 07:36:37 +0000] [12] [CRITICAL] WORKER TIMEOUT (pid:1243)
[017-03-01 07:36:37 +0000] [1203] [INFO] Worker exiting (pid: 1203)
[017-03-01 07:36:37 +0000] [1225] [INFO] Worker exiting (pid: 1225)
[017-03-01 07:36:37 +0000] [1243] [INFO] Worker exiting (pid: 1243)
[017-03-01 07:36:37 +0000] [1234] [INFO] Worker exiting (pid: 1234)
[017-03-01 07:36:37 +0000] [1256] [INFO] Booting worker with pid: 1256
[017-03-01 07:36:37 +0000] [12] [DEBUG] 14 workers
[017-03-01 07:36:37 +0000] [1257] [INFO] Booting worker with pid: 1257
[017-03-01 07:36:37 +0000] [1262] [INFO] Booting worker with pid: 1262
[017-03-01 07:36:37 +0000] [1265] [INFO] Booting worker with pid: 1265
[017-03-01 07:36:37 +0000] [12] [DEBUG] 16 workers
[017-03-01 07:36:40 +0000] [1262] [DEBUG] GET /healthcheck

์—…๋ฐ์ดํŠธ - ๋ฐฉ๊ธˆ gunicorn์—์„œ gevent(http://flask.pocoo.org/docs/0.12/deploying/wsgi-standalone/#gevent)๋กœ ์ „ํ™˜ํ–ˆ๊ณ  ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‚ด ์œ„์˜ ์˜๊ฒฌ์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค. https://github.com/benoitc/gunicorn/issues/1194#issuecomment -283269046

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

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

[2017-03-30 23:38:37 +0000] [5] [INFO] Starting gunicorn 19.7.1
[2017-03-30 23:38:37 +0000] [5] [INFO] Listening at: http://0.0.0.0:8000 (5)
[2017-03-30 23:38:37 +0000] [5] [INFO] Using worker: eventlet
[2017-03-30 23:38:38 +0000] [8] [INFO] Booting worker with pid: 8
[2017-03-30 23:38:40 +0000] [9] [INFO] Booting worker with pid: 9
[2017-03-30 23:38:41 +0000] [11] [INFO] Booting worker with pid: 11
[2017-03-30 23:38:42 +0000] [12] [INFO] Booting worker with pid: 12
[2017-03-30 23:38:42 +0000] [10] [INFO] Booting worker with pid: 10
[2017-03-30 23:40:08 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:8)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:10)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:11)
[2017-03-30 23:40:12 +0000] [5] [CRITICAL] WORKER TIMEOUT (pid:12)
[2017-03-30 23:40:13 +0000] [8] [INFO] Worker exiting (pid: 8)
[2017-03-30 23:40:13 +0000] [10] [INFO] Worker exiting (pid: 10)
[2017-03-30 23:40:16 +0000] [16] [INFO] Booting worker with pid: 16
[2017-03-30 23:40:16 +0000] [17] [INFO] Booting worker with pid: 17
[2017-03-30 23:40:18 +0000] [18] [INFO] Booting worker with pid: 18
[2017-03-30 23:40:20 +0000] [19] [INFO] Booting worker with pid: 19
[2017-03-30 23:40:23 +0000] [20] [INFO] Booting worker with pid: 20

์ด๊ฒƒ์€ ๋‚ด ๋ถ€๋ถ„์—์„œ ์•ฝ๊ฐ„์˜ ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋‚ด ํ”„๋กœ์ ํŠธ ๋Œ€์‘๋ฌผ ์ค‘ ํ•˜๋‚˜์™€ ๋™์ผํ•œ ๋™์ž‘์ด ์•„๋‹™๋‹ˆ๋‹ค(๊ฑฐ์˜ ๋™์ผํ•œ AWS/CloudFormation/ALB/ECS ๋ฐฐํฌ์—์„œ ์œ ์‚ฌํ•˜์ง€๋งŒ ๋™์ผํ•˜์ง€ ์•Š์€ ์ฝ”๋“œ๋ฒ ์ด์Šค ์‚ฌ์šฉ). ๊ทธ๋Ÿฌ๋‚˜ ALB, ECS, Docker ๋ฐ gunicorn ๊ฐ„์˜ ์ƒํ˜ธ ์ž‘์šฉ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ํ†ต์ฐฐ๋ ฅ์„ ๋ถˆ๋Ÿฌ์ผ์œผํ‚ฌ ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ๋ณด๊ณ ํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋น„์Šทํ•œ ์„ค์ •(ELB->ECS Docker Container->Gunicorn->Django๋ฅผ ์‹คํ–‰ํ•˜๋Š” convox)์ด ์žˆ์œผ๋ฉฐ ๋‹ค์Œ ๊ตฌ์„ฑ ๋ณ€๊ฒฝ์ด ๋„์›€์ด ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

keepalive = 75 # needs to be longer than the ELB idle timeout
timeout = 90
worker_class = 'gevent'

ELB ์œ ํœด ์‹œ๊ฐ„ ์ œํ•œ์„ 60์ดˆ๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ์„ค์ •์„ ๋ณ€๊ฒฝํ•˜๊ธฐ ์ „์— ์—ฐ๊ฒฐ ์œ ์ง€, ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฐ ๋™๊ธฐํ™” ์ž‘์—…์ž์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ฐ’์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ์ด ๋ฌธ์ œ๋Š” UTC 4์›” 10์ผ ์˜ค์ „ 4์‹œ์— ํ‘œ์‹œ๋˜๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ์•ฑ์€ ์ง€๋‚œ ๋ชฉ์š”์ผ ์ดํ›„ ์•„๋ฌด๋Ÿฐ ๋ณ€๊ฒฝ ์—†์ด ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์Œ“๊ธฐ๋งŒ ํ•˜๋ฉด ๋„์ปค๊ฐ€ ์—†์ง€๋งŒ ๋ฒ ์–ด aws ์ธ์Šคํ„ด์Šค์—๋Š” ELB ๋’ค์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. osx์—์„œ NP๋ฅผ ์ž‘๋™ํ•˜์ง€๋งŒ ELB์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ubuntu16์ด ์ž˜๋ ธ์Šต๋‹ˆ๋‹ค. gevent ์ž‘์—…์ž ํด๋ž˜์Šค๊ฐ€ [๋‚˜๋ฅผ ์œ„ํ•ด] ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์˜ ๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?
https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx

@erikcw ๋Š” ์ด ์†”๋ฃจ์…˜์ด ์ž‘๋™ํ•˜๋Š” ๊ฒƒ์„ ์ฐพ์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ์ข…๋ฃŒํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๋ˆ„๊ตฌ๋“ ์ง€ Gunicorn ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฐ ์—ฐ๊ฒฐ ์œ ์ง€ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋†’์ธ ํ›„ ์ด๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ๋ง์”€ํ•ด ์ฃผ์‹ญ์‹œ์˜ค.

๋˜๋Š” ELB์˜ ์œ ํœด ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋‚ฎ์ถ”์‹ญ์‹œ์˜ค.

์•ผ์ƒ์˜ ํด๋ผ์ด์–ธํŠธ(๋˜๋Š” ์‚ฌ์•…ํ•œ ํด๋ผ์ด์–ธํŠธ)๊ฐ€ ELB์ฒ˜๋Ÿผ ํ–‰๋™ํ•˜์—ฌ ๋™์ผํ•œ ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜๋Š” ์—†๋‚˜์š”?

@six8 ๋„ค. ELB๋„ ์ด๊ฒƒ์œผ๋กœ๋ถ€ํ„ฐ ๋‹น์‹ ์„ ๋ณดํ˜ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ฌธ์„œ์—์„œ๋Š” ์ด์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. http://docs.gunicorn.org/en/latest/design.html#choosing -a-worker-type

์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ์ด ์œ„ํ˜‘์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๊ณ  ELB ์—์ง€๋‚˜ ๋’ค์— Gunicorn์„ ๋ฐฐ์น˜ํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋…ผ์˜๋œ ๋ฌธ์ œ๋Š” ELB ์ž์ฒด๋กœ ์ธํ•œ ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ์ž…๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ์—ญ๋ฐฉํ–ฅ ํ”„๋ก์‹œ ์—†์ด ๋™๊ธฐํ™” ์ž‘์—…์ž๊ฐ€ ์žˆ๋Š” ELB ๋’ค์—์„œ gunicorn์ด ์ž‘๋™ํ•˜๋„๋ก ํ•˜๋Š” ๊ถŒ์žฅ ๊ตฌ์„ฑ์„ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š”์— gunicorn ํ˜ธ์ถœ์„ ๋ณ€๊ฒฝํ•˜์—ฌ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ์˜ ์†”๋ฃจ์…˜์„ @erikcw ์‹œ๋„ :

CMD [ "gunicorn", "-k", "gevent", "--timeout", "10", "--keep-alive", "75", "--paste", "/etc/jzoo/app.ini" ]

๋ถˆํ–‰ํžˆ๋„ ๋„์›€์ด๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

[2017-07-04 08:36:23 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:24)
[2017-07-04 08:38:11 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:28)
[2017-07-04 08:39:39 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:29)
[2017-07-04 08:44:14 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:25)
[2017-07-04 08:44:55 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:31)

Gunicorn ๋™๊ธฐํ™” ์ž‘์—…์ž๊ฐ€ ์žˆ๋Š” ALB ๋’ค์˜ ECS์—์„œ ์‹คํ–‰๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์•„์ง ์–ด๋–ค ๋ฌธ์ œ๋„ ๋ณด์ง€ ๋ชปํ–ˆ๋‹ค.

๋ˆ„๊ตฌ๋‚˜ ์žฌํ˜„ ๊ฐ€๋Šฅํ•œ ๋ฐฐํฌ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์Œ“์ด๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. ELB์™€ ํ•จ๊ป˜ AWS์—์„œ Kubernetes๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ๋ฌธ์ œ๋ฅผ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ 8๋ช…์˜ ์ž‘์—…์ž๊ฐ€ ์šด์˜ ์ค‘์ž…๋‹ˆ๋‹ค. https://serverfault.com/questions/782022/keepalive-setting-for-gunicorn-behind-elb-without-nginx/ ๋‹น, ์šฐ๋ฆฌ๋Š” keepalive , ๊ทธ๋ฆฌ๊ณ  ์ด ์Šค๋ ˆ๋“œ ๋‹น ์‹œ๋„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค ๋Œ€์‹  gevent ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ˜„์žฌ ์‹คํŒจํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ์ž์ฒด์ ์œผ๋กœ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์ฐจ๋‹จ/์œ ๋ฐœํ•ด์„œ๋Š” ์•ˆ ๋˜๋Š” API ํ˜ธ์ถœ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. sync ์ž‘์—…์ž์—๊ฒŒ ๋ฌด์Šจ ์ผ์ด ์ผ์–ด๋‚˜๊ณ  ์žˆ๋Š”์ง€ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์˜ ๋ช‡ ๊ฐ€์ง€ ์ข‹์€ ์ง€์นจ์— ๋”ฐ๋ผ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋”๋ผ๋„ ํ”„๋กœ๋•์…˜์— ๋ฐฐํฌํ•˜๊ธฐ ์ „์— ์ง„ํ–‰ ์ค‘์ธ ์ž‘์—…์— ๋Œ€ํ•ด ์ข€ ๋” ํ™•์‹ ์„ ๊ฐ–๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

--worker-class๋ฅผ --worker-class gevent ์„ค์ •ํ•˜๋ฉด ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋Œ“๊ธ€๊ณผ ๋„์›€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

@wichert ์ด๊ฒƒ์€ ๋งค์šฐ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. gevent ์ž‘์—…์ž์™€ ํ•จ๊ป˜ ์ž‘์—…์ž๋Š” ์ค‘์žฌ์ž์—๊ฒŒ ๋ชจ๋“  ์—ฐ๊ฒฐ๊ณผ ๋ณ„๋„์˜ ๊ทธ๋ฆฐ๋ ›์—์„œ ํ™œ์„ฑ ์ƒํƒœ๋ฅผ ์•Œ๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฐ๊ฒฐ ์œ ์ง€ ์„ค์ •์€ ์ด๊ฒƒ์— ์ „ํ˜€ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. gevent๊ฐ€ ์„ค๊ณ„๋œ ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋“ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฌธ์ œ๊ฐ€ ์žˆ๊ฑฐ๋‚˜ ์ด๋Ÿฌํ•œ ๋‹ค๋ฅธ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๊ณตํ†ต์ ์œผ๋กœ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ • ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์€ ์ด ๋ฌธ์ œ๋ฅผ ์žฌํ˜„ํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ์ œ๊ณตํ•˜์‹ญ์‹œ์˜ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ์žฌํ˜„ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์žฌํ˜„ํ•  ๋‹จ๊ณ„๊ฐ€ ์—†์œผ๋ฉด ๋‹ซ๊ณ  ์‹ถ์€ ์ถฉ๋™์ด ๋“ญ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜๊ฒฌ์—๋Š” ์—ฌ๋Ÿฌ ๊ถŒ์žฅ ์‚ฌํ•ญ๊ณผ ๋งค์šฐ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ๋ฌปํ˜€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋กœ ๋ฌด์—‡์„ ํ•ด์•ผํ• ์ง€ ์•Œ๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

@tilgovi gevent ์— ์ž‘์—…์ž ํด๋ž˜์Šค๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์„ ๋•Œ(์˜ˆ: ๊ธฐ๋ณธ ๋™๊ธฐํ™” ์ž‘์—…์ž ์‚ฌ์šฉ) ์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์„ค์ •์€ pypy3(PyPy 5.8.0-beta0), falcon 1.2 ๋“ฑ์„ ์‚ฌ์šฉํ•˜๋Š” virtualenv์ž…๋‹ˆ๋‹ค(Falcon์— ๋Œ€ํ•œ ์ดํ•ด๋Š” pypy3์—์„œ ๊ณต์‹์ ์œผ๋กœ ์ง€์›๋˜์ง€ ์•Š์Œ). ๋‚˜๋Š” https://github.com/7ideas/cookiecutter-falcon ์—์„œ cookiecutter๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ๋ชจ๋“  ์ตœ์‹  ํŒจํ‚ค์ง€๋กœ ์—…๊ทธ๋ ˆ์ด๋“œํ–ˆ์œผ๋ฉฐ ๋ธŒ๋ผ์šฐ์ €์—์„œ sample_resource๋ฅผ ๋กœ๋“œํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜๊ณ  httpie๋กœ ์—ฌ๋Ÿฌ ๋ฒˆ ์น˜๋ฉด ๊ฐ„ํ—์ ์œผ๋กœ ์ž‘์—…์ž ์ถฉ๋Œ ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค( ์˜ˆ๋ฅผ ๋“ค์–ด ์š”์ฒญ์ด ์ง€์—ฐ๋˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. ์š”์ฒญ์„ ์ทจ์†Œํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฒฐ๊ตญ ์‘๋‹ตํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋™๊ธฐํ™”์˜ ๊ธฐ๋ณธ ์ž‘์—…์ž ํด๋ž˜์Šค์—์„œ๋งŒ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. gevent๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ์ง€์ •ํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

@jhillhouse92 ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

@tilgovi ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฌธ์ œ๊ฐ€ ๊ณ„์† ๋ฐœ์ƒํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์ผ ๋” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ๋” ์ •ํ™•ํ•œ ์ •๋ณด๋กœ ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฒŒ์‹œํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ณ„์† ์—ด์–ด ๋‘์‹ญ์‹œ์˜ค. ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ์˜ณ์•˜์ง€๋งŒ ์ผ๋ฐ˜์ ์ธ ์ฃผ์ œ๋Š” gunicorn ์ž‘์—…์ž(์•„๋งˆ๋„ sync ์ž‘์—…์ž ํด๋ž˜์Šค, tbd์™€ ํ•จ๊ป˜)๊ฐ€ AWS/ELB๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐฐํฌ๋œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ํ•จ๊ป˜ gunicorn์„ ์‚ฌ์šฉํ•  ๋•Œ ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์ •ํ™•ํ•œ ๋ฌธ์ œ๋ฅผ ๋ถ„๋ฆฌํ•˜์ง€ ์•Š์•˜๋”๋ผ๋„ ์—ฌ๊ธฐ์— ๋ญ”๊ฐ€ ์ž˜๋ชป๋œ ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ํŒŒ๊ณ ๋“ค ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚ด์ผ ์—…๋ฐ์ดํŠธ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์–ธ๊ธ‰ํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”, ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ์Šคํƒ์„ ์‚ฌ์šฉํ•˜์—ฌ Docker/AWS/ELB๊ฐ€ ์•„๋‹Œ ๋กœ์ปฌ์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ๊ฒฝํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €๋Š” gevent๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์•ก์„ธ์Šค ๋กœ๊ทธ๋ฅผ ์บก์ฒ˜ํ•˜๊ณ  AWS/ELB๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์•ฑ์„ ๋ฐฐํฌํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

๋„์ปค ํŒŒ์ผ ๋ช…๋ น:

FROM cortex/base

CMD ["gunicorn", "-w", "8", "-b", "0.0.0.0:5000", "--capture-output", "--enable-stdio-inheritance", "--access-logfile", "-", "--worker-class", "gevent", "-t", "60", "--log-level", "debug", "app:app"]

์ œํ•œ ์„ค์ •์— ๊ด€๊ณ„์—†์ด ์˜ค๋ฅ˜ ์ฝ”๋“œ 14์™€ ๊ด€๋ จํ•˜์—ฌ ๋ฏธ์นœ OOM ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์™€ ๊ด€๋ จํ•˜์—ฌ ๋‹ค๋ฅธ ์‚ฌ๋žŒ์ด ์ด๊ฒƒ์„ ๋ณธ ์ ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ์ด์ „์—๋Š” ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ตฌ์„ฑ์œผ๋กœ๋Š” ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์žฌํ˜„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

[2017-07-19 18:27:39 +0000] [34] [ERROR] Exception in worker process
Traceback (most recent call last):
  File "/usr/local/lib/python3.5/site-packages/gunicorn/arbiter.py", line 578, in spawn_worker
    worker.init_process()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/ggevent.py", line 190, in init_process
    super(GeventWorker, self).init_process()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/base.py", line 126, in init_process
    self.load_wsgi()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/workers/base.py", line 135, in load_wsgi
    self.wsgi = self.app.wsgi()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/base.py", line 67, in wsgi
    self.callable = self.load()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
    return self.load_wsgiapp()
  File "/usr/local/lib/python3.5/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
    return util.import_app(self.app_uri)
  File "/usr/local/lib/python3.5/site-packages/gunicorn/util.py", line 376, in import_app
    __import__(module)
  File "/code/app/__init__.py", line 2, in <module>
    from flask_alchy import Alchy
  File "/usr/local/lib/python3.5/site-packages/flask_alchy.py", line 8, in <module>
    from flask_sqlalchemy import SQLAlchemy
  File "/usr/local/lib/python3.5/site-packages/flask_sqlalchemy/__init__.py", line 18, in <module>
    import sqlalchemy
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/__init__.py", line 9, in <module>
    from .sql import (
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/__init__.py", line 8, in <module>
    from .expression import (
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/expression.py", line 34, in <module>
    from .functions import func, modifier, FunctionElement, Function
  File "/usr/local/lib/python3.5/site-packages/sqlalchemy/sql/functions.py", line 11, in <module>
    from . import sqltypes, schema
  File "<frozen importlib._bootstrap>", line 969, in _find_and_load
  File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 673, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 658, in exec_module
  File "<frozen importlib._bootstrap_external>", line 763, in get_code
  File "<frozen importlib._bootstrap_external>", line 816, in get_data
OSError: [Errno 14] Bad address

๋ฐ˜๋ณตํ•ด์„œ ๋งํ•˜์ง€๋งŒ, ๋„์ปค ์—†์ด๋Š” ๋กœ์ปฌ์—์„œ ์ด๊ฒƒ์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. Docker์—์„œ ๋กœ์ปฌ๋กœ ์ด๊ฒƒ์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์™€ ์‹œ๊ฐ„ ์ดˆ๊ณผ ๋ฌธ์ œ๋Š” ๋ถ„๋ช…ํžˆ Docker/AWS/ELB ์Šคํƒ์—์„œ๋งŒ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค(์ €๋ฅผ ์œ„ํ•ด).

@tilgovi ๋‚ด๊ฐ€ ์ฒ˜์Œ์—

gunicorn -k gevent --timeout 90 --keep-alive 75 --paste /etc/jzoo/app.ini "$@"

.ini ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

[DEFAULT]
sqlalchemy.url = postgresql://XXXX

[app:main]
use = egg:jzoo.api.admin

[server:main]
use = egg:gunicorn#main
bind = 0.0.0.0:5000
workers = 4
preload_app = true
loglevel = warning

# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic,jzoo

# .. more logging configuration

ํŠธ๋ž˜ํ”ฝ ์–‘์€ ์š”์ธ์ด ์•„๋‹Œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํŠธ๋ž˜ํ”ฝ์ด ๊ฑฐ์˜ ์—†๋Š” QA ํ™˜๊ฒฝ์—์„œ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ด…๋‹ˆ๋‹ค.

์–ผ๋งˆ๋‚˜ ์ž์ฃผ ์ด๋Ÿฐ ์ผ์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด๋ฉด ์ด๊ฒƒ์ด ์•ฑ ๋‹ค์‹œ ์‹œ์ž‘๊ณผ ๊ด€๋ จ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์•ฝ๊ฐ„ ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์กฐ์‚ฌ ๊ฒฐ๊ณผ, ์•„๋งˆ๋„ gunicorn์ด ์•„๋‹ˆ๋ผ ๋„คํŠธ์›Œํฌ ์—ฐ๊ฒฐ ์˜ค๋ฅ˜๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์„ค์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Postgresql ์„œ๋ฒ„๋Š” EC2์˜ Docker์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋„์ปค ์ด๋ฏธ์ง€๋Š” ๊ณต์‹ ํฌ์ŠคํŠธ๊ทธ๋ ˆ์Šค 9.6์ž…๋‹ˆ๋‹ค.
  • ์•ฑ ์„œ๋ฒ„๋Š” EC2 ์™ธ๋ถ€ VM์˜ Docker์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ๋„์ปค ์ด๋ฏธ์ง€๋Š” ๊ณต์‹ python 3.6์ž…๋‹ˆ๋‹ค.
  • ํฌํŠธ 5432/tcp๋งŒ AWS ๋ณด์•ˆ ๊ทธ๋ฃน์—์„œ ์—ด๋ฆฝ๋‹ˆ๋‹ค.

ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ์•ฑ ์„œ๋ฒ„์—์„œ postgres ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋Œ€๋ถ€๋ถ„์˜ ์š”์ฒญ์€ ํ•˜๋‚˜๋ฅผ ์ œ์™ธํ•˜๊ณ ๋Š” ๊ดœ์ฐฎ์•˜์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ์ฟผ๋ฆฌ๋Š” ์˜์›ํžˆ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์œผ๋กœ ๋ณด์ด๋ฉฐ, ์ด๋Š” gunicorn ์ž‘์—…์ž ์‹œ๊ฐ„์„ ์ดˆ๊ณผํ•ฉ๋‹ˆ๋‹ค.

์•ฑ์„ ๋กœ์ปฌ์—์„œ ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

์•ฑ ์„œ๋ฒ„๋ฅผ ๊ณ ์ •ํ™”ํ•˜์ง€ ์•Š์œผ๋ฉด ๋ฌธ์ œ๋„ ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

๋‚ด ์ž„์‹œ ์ˆ˜์ • ์‚ฌํ•ญ์€ AWS ๋ณด์•ˆ ๊ทธ๋ฃน ์„ค์ •์„ ํ†ตํ•ด ์•ฑ ์„œ๋ฒ„์™€ postgres ์„œ๋ฒ„ ๊ฐ„์˜ ๋ชจ๋“  ์—ฐ๊ฒฐ์„ ์—ฌ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ ๋ชจ๋“  ๊ฒƒ์ด ๋‹ค์‹œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Python ์ปจํ…Œ์ด๋„ˆ์™€ AWS ๊ฐ„์— ์—ฐ๊ฒฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. AWS ๋กœ๊ทธ ์ŠคํŠธ๋ฆผ์„ ์ฒ ์ €ํžˆ ๊ฒ€ํ† ํ•œ ํ›„ ์—…๋ฐ์ดํŠธํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!! ELB ๋ฐ ์ธ์Šคํ„ด์Šค ํ”„๋กœํ† ์ฝœ์„ HTTP์—์„œ TCP๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค ๐Ÿ‘

๋ฌธ์ œ๋Š” AWS์—๋งŒ ๊ตญํ•œ๋œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ Gunicorn๊ณผ ๊ฒฐํ•ฉํ•  ๋•Œ Docker ์ž์ฒด์— ๊ตญํ•œ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ ์–ด๋„ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” gevent ์—์„œ๋„ ์ด๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@tilgovi ๋‹ค์Œ์€ ์ด ์˜ค๋ฅ˜๋ฅผ ์žฌํ˜„ํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์•ฑ์ž…๋‹ˆ๋‹ค(

app.py:

import falcon


class HelloResource:
    def on_get(self, req, resp):
        resp.media = {'info': 'hello world'}


app = falcon.API()
app.add_route('/', HelloResource())

๋„์ปค ํŒŒ์ผ:

FROM python:3.6
WORKDIR /code
RUN pip install gunicorn falcon
COPY app.py .
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]

์‹คํ–‰ํ•˜๋ ค๋ฉด: docker build -t gunicorn-and-docker . && docker run -p 8000:8000 -it --rm gunicorn-and-docker

๋กœ๊ทธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค(์ ์–ด๋„ Docker 17.06.2-ce-mac27(19124)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” macOS Sierra์˜ ๊ฒฝ์šฐ).

[2017-09-23 22:31:00 +0000] [1] [INFO] Starting gunicorn 19.7.1
[2017-09-23 22:31:00 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
[2017-09-23 22:31:00 +0000] [1] [INFO] Using worker: sync
[2017-09-23 22:31:00 +0000] [9] [INFO] Booting worker with pid: 9
[2017-09-23 23:22:45 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-09-23 23:22:45 +0000] [9] [INFO] Worker exiting (pid: 9)
[2017-09-23 23:22:45 +0000] [11] [INFO] Booting worker with pid: 11
[2017-09-23 23:39:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:11)
[2017-09-23 23:39:46 +0000] [11] [INFO] Worker exiting (pid: 11)
[2017-09-23 23:39:46 +0000] [13] [INFO] Booting worker with pid: 13
[2017-09-23 23:41:10 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:13)
[2017-09-23 23:41:10 +0000] [13] [INFO] Worker exiting (pid: 13)
[2017-09-23 23:41:10 +0000] [15] [INFO] Booting worker with pid: 15
[2017-09-23 23:42:27 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:15)
[2017-09-23 23:42:27 +0000] [15] [INFO] Worker exiting (pid: 15)
[2017-09-23 23:42:27 +0000] [17] [INFO] Booting worker with pid: 17
[2017-09-23 23:43:44 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:17)
[2017-09-23 23:43:44 +0000] [17] [INFO] Worker exiting (pid: 17)
[2017-09-23 23:43:44 +0000] [19] [INFO] Booting worker with pid: 19
[2017-09-24 18:37:12 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:19)
[2017-09-24 18:37:12 +0000] [19] [INFO] Worker exiting (pid: 19)
[2017-09-24 18:37:12 +0000] [21] [INFO] Booting worker with pid: 21
[2017-09-24 19:49:20 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:21)
[2017-09-24 19:49:20 +0000] [21] [INFO] Worker exiting (pid: 21)
[2017-09-24 19:49:20 +0000] [23] [INFO] Booting worker with pid: 23
[2017-09-24 19:50:37 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:23)
[2017-09-24 19:50:37 +0000] [23] [INFO] Worker exiting (pid: 23)
[2017-09-24 19:50:37 +0000] [25] [INFO] Booting worker with pid: 25
[2017-09-24 20:25:48 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:25)
[2017-09-24 20:25:48 +0000] [25] [INFO] Worker exiting (pid: 25)
[2017-09-24 20:25:48 +0000] [27] [INFO] Booting worker with pid: 27

์•ˆ๋…•ํ•˜์„ธ์š”,

๋‚˜๋Š” ์ตœ๊ทผ์— ๊ฐ™์€ ๋ฌธ์ œ์— ๋ถ€๋”ช์ณค๋‹ค.
๋‚ด ๊ฒฝ์šฐ(ECS + gunicorn 19.7.1 + Django 1.11.5) ๋‚˜๋Š” (๋ถ„๋ช…ํžˆ) ์ž‘์—… ์ •์˜์—์„œ ์ปจํ…Œ์ด๋„ˆ ์ „์šฉ ๋ฉ”๋ชจ๋ฆฌ ์–‘(128MB์—์„œ 256MB๋กœ)์„ ์ฆ๊ฐ€์‹œ์ผœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.
์ง€๊ธˆ๊นŒ์ง€ ๋” ์ด์ƒ ์˜ค๋ฅ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋ฐœ์ƒํ•˜๋ฉด ์—ฌ๊ธฐ์— ์‹ ๊ณ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์— ์ฝ”๋Ÿฌ์Šค๋ฅผ ์กฐ๊ธˆ ์ถ”๊ฐ€ํ–ˆ์ง€๋งŒ gevent๋กœ ์ „ํ™˜ํ•ด์•ผ๋งŒ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์šด์ด์—†๋Š” ๋™๊ธฐํ™” ์ž‘์—…์ž์™€ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ 90์œผ๋กœ ๋Š˜๋ฆฌ๊ณ  ์—ฐ๊ฒฐ ์œ ์ง€๋ฅผ 75๋กœ ๋Š˜๋ฆฌ๋ ค๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ์ด ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ๋‚ด ELB๋Š” HTTP๊ฐ€ ์•„๋‹Œ TCP ์ˆ˜์ค€ ์ „๋‹ฌ๋งŒ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ข‹์•„, ์ด๊ฒƒ์„ ์„ค๋ช…ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์ฐธ์กฐ๋ฅผ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. [1]

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

[1] https://cloudavail.com/2013/12/21/aws-elb-pre-open-connection-expose-part-1/

์ด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  gevent/eventlet/asyncio๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ ค๋ฉด ์Šค๋ ˆ๋“œ ์ž‘์—…์ž๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค( --threads ์„ค์ • ์ œ๊ณต).

@tilgovi ์œ„์˜ ์˜ˆ๋ฅผ ๋ณด๋ฉด gevent ์ž‘์—…์ž์—๊ฒŒ๋„ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@jmagnusson ๊ท€ํ•˜์˜ ์˜ˆ(์ด ์ฃผ์„: https://github.com/benoitc/gunicorn/issues/1194#issuecomment-331740187)์—์„œ ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

[2017-09-23 22:31:00 +0000] [1] [์ •๋ณด] ์ž‘์—…์ž ์‚ฌ์šฉ: ๋™๊ธฐํ™”

@tilgovi ์‚ฌ์‹ค์ด์ง€๋งŒ gevent ์ž‘์—…์ž์—๊ฒŒ๋„ ์ด๊ฒƒ์„ ๊ฒฝํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค. gevent๋กœ ์žฌ์ƒ์‚ฐํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ–๋„๋ก ๋…ธ๋ ฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ €์ผ ์ˆ˜๋„ ์žˆ์ง€๋งŒ EC2 ๋ณด์•ˆ ๊ทธ๋ฃน -> ์ธ๋ฐ”์šด๋“œ ๊ทœ์น™์—๋Š” ๋‹จ์ผ IP(๋‚ด IP: XX.XX.XX.XX)๋งŒ ํ—ˆ์šฉํ•˜๋Š” ํฌํŠธ 5000(์—ฌ๊ธฐ์„œ๋Š” gunicorn)์— ๋Œ€ํ•œ ์‚ฌ์šฉ์ž ์ง€์ • TCP ๊ทœ์น™์ด ์žˆ์Šต๋‹ˆ๋‹ค. /32), ์ด๊ฒƒ์„ ๋ชจ๋“  IP๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค.

๋‚˜๋„ ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚œ๋‹ค.

[2018-01-02 16:38:03 +0800] [24355] [INFO] Starting gunicorn 19.7.1
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] Arbiter booted
[2018-01-02 16:38:03 +0800] [24355] [INFO] Listening at: http://0.0.0.0:8080 (24355)
[2018-01-02 16:38:03 +0800] [24355] [INFO] Using worker: gevent
[2018-01-02 16:38:03 +0800] [24358] [INFO] Booting worker with pid: 24358
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] 1 workers
[2018-01-02 16:38:03 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:04 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:05 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:06 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:07 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:08 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:09 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:10 +0800] [24358] [INFO] worker pid 24358 notify
[2018-01-02 16:38:10 +0800] [24358] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:38:10 +0800] [24358] [DEBUG] Closing connection. 
[2018-01-02 16:38:41 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24358)
[2018-01-02 16:38:41 +0800] [24358] [INFO] Worker exiting (pid: 24358)
[2018-01-02 16:38:41 +0800] [24381] [INFO] Booting worker with pid: 24381
[2018-01-02 16:38:41 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:42 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:43 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:44 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:45 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:46 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:38:47 +0800] [24381] [INFO] worker pid 24381 notify
......
[2018-01-02 16:48:20 +0800] [24381] [INFO] worker pid 24381 notify
[2018-01-02 16:48:51 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24381)
[2018-01-02 16:48:51 +0800] [24381] [INFO] Worker exiting (pid: 24381)
[2018-01-02 16:48:51 +0800] [24703] [INFO] Booting worker with pid: 24703
[2018-01-02 16:48:51 +0800] [24703] [INFO] worker pid 24703 notify
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] Closing connection. 

๋””๋ฒ„๊ทธ ๋กœ๊ทธ worker pid {WORKER_PID} notify .

๋””๋ฒ„๊ทธ ๋กœ๊ทธ์— ๋”ฐ๋ฅด๋ฉด,

  1. ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•˜๋‚˜์˜ ์š”์ฒญ์„ ๋ฐ›์€ ๊ฒฝ์šฐ์—๋งŒ ์•Œ๋ฆผ์ด ์ง„ํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์š”์ฒญ์ด ์žˆ๋“  ์—†๋“  ๋งˆ์Šคํ„ฐ๋Š” 30์ดˆ ํ›„์— ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๋ฅผ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
  2. 1์ฐจ ์š”์ฒญ์ด ์ข…๋ฃŒ๋˜๋ฉด ๋ฐ”๋กœ 2์ฐจ ์š”์ฒญ์„ ๋ณด๋ƒˆ๋Š”๋ฐ 2์ฐจ ์š”์ฒญ์ด ์ฐจ๋‹จ๋˜์–ด ์‘๋‹ต์ด ์—†์Šต๋‹ˆ๋‹ค. 30์ดˆ ์‹œ๊ฐ„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ•˜๋ฉด ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ์ƒˆ ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‘ ๋ฒˆ์งธ ์š”์ฒญ์— ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ์„œ๋ฒ„๊ฐ€ ๋‹ค์‹œ ์ค‘๋‹จ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  3. ์ž‘์—…์ž ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ •์ง€๋˜๋ฉด SIGTERM ์™€ ๊ฐ™์€ ๋งˆ์Šคํ„ฐ๋กœ๋ถ€ํ„ฐ ์‹ ํ˜ธ๋ฅผ ์ˆ˜์‹ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Graceful timeout์— ๋„๋‹ฌํ•˜๋ฉด ๋งˆ์Šคํ„ฐ๋Š” SIGKILL ๊ฐ•์ œ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.
Python: 3.6.3
Gevent: 1.2.2
Gunicorn: 19.7.1
RUN CMD: gunicorn --worker-class gevent --log-level debug --bind 0.0.0.0:8080 app

์ฃผ์˜: eventlet ๋ฅผ ์ž‘์—…์ž๋กœ ์‚ฌ์šฉํ•˜๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ์ผ์ข…์˜ ๊ตฌ์‹์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ํŒ๋‹จํ•  ์ˆ˜ ์žˆ๋Š” ํ•œ ๊ด€์ฐฐ๋œ ๋™์ž‘์€ AWS Classic Load Balancer๊ฐ€ ์‚ฌ์ „ ๊ฐœ๋ฐฉ ์ตœ์ ํ™”๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด ์ตœ์ ํ™”๋Š” ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ์ž‘๋™ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์„ค๋ช…์„œ์— ๋”ฐ๋ผ Classic Load Balancer์—์„œ๋งŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค. Application Load Balancer๋กœ ์ „ํ™˜ํ•˜๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด ๋ธ”๋กœ๊ทธ ๊ฒŒ์‹œ๋ฌผ์— ์„ค๋ช…๋œ ๋Œ€๋กœ AWS์— ์‚ฌ์ „ ๊ฐœ๋ฐฉ ์ตœ์ ํ™”๋ฅผ ๋น„ํ™œ์„ฑํ™”ํ•˜๊ฑฐ๋‚˜ Gunicorn์— ๋Œ€ํ•œ ์ž‘์—…์ž ์ œํ•œ ์‹œ๊ฐ„์„ ๋Š˜๋ฆฌ๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@tilgovi FWIW ๋‚˜๋Š” ์ด๊ฒƒ์„ ALB์—์„œ ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ €๋Š” ํด๋ž˜์‹ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ๋ฅผ ์‚ฌ์šฉํ•œ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค.

@tilgovi ๋‚˜ ์—ญ์‹œ ํด๋ž˜์‹์„ ์‚ฌ์šฉํ•œ ์ ์ด ์—†๋Š” ALB ์ „์šฉ ํ™˜๊ฒฝ์—์„œ ์ด๊ฒƒ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ด€์ฐฐํ–ˆ๋‹ค. ์ž‘์—…์ž ์‹œ๊ฐ„ ์ดˆ๊ณผ ์กฐ์ •์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์šฐ๋ฆฌ๋Š” ์ด๊ฒƒ์„ ๊ณ„์† ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

@tilgovi ๋‚˜๋Š” ์ด๊ฒƒ์„ ๋งŒ๋‚ฌ๋‹ค. ์ €๋Š” AWS๋ฅผ ์‚ฌ์šฉํ•œ ์ ์ด ์—†์Šต๋‹ˆ๋‹ค.

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ ์ด๊ฒƒ์„ ์žฌํ˜„ํ•˜๊ณ  ๋””๋ฒ„๊น…์„ ์‹œ๋„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ALB๋กœ ์žฌ์ƒ์‚ฐํ•  ์ˆ˜ ์—†๊ณ  AWS ์™ธ๋ถ€์—์„œ ์žฌ์ƒ์‚ฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

@xgfone ์ž์‹ ์˜ ๋ฌธ์ œ๋ฅผ ์—ด๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์˜ ์ œ๋ชฉ์€ "docker + AWS"์ž…๋‹ˆ๋‹ค.

AWS ๋กœ๋“œ ๋ฐธ๋Ÿฐ์„œ์—์„œ Docker ์—†์ด ์ด๊ฒƒ์„ ๊ฒฝํ—˜ํ•œ ์‚ฌ๋žŒ์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ์•ฝ๊ฐ„ ํ˜ผ๋ž€ ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค, ๋‚˜๋Š” ์ธ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค :)

๋‚ด ์ธ์ƒ์€ ๋ฌธ์ œ๊ฐ€ ์‹ค์ œ๋กœ Docker์™€ ๋” ๊ด€๋ จ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ ์–ด๋„ ๋กœ์ปฌ ์ปดํ“จํ„ฐ์˜ Docker ๋‚ด๋ถ€์—์„œ ์—ฌ๋Ÿฌ gunicorn ๋™๊ธฐํ™” ์ž‘์—…์ž๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ๊ณผ ์ •ํ™•ํžˆ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ตฌ์„ฑ์€ ๋ฒ ์–ด๋ฉ”ํƒˆ ๋ฐ Digital Ocean์—์„œ ๊ฐ€์ƒํ™”๋œ Ubuntu ๋ฐ RHEL ์‹œ์Šคํ…œ์—์„œ Docker ์—†์ด๋„ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

workers = 2
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

Docker ๋‚ด๋ถ€(RHEL, ๋‹ค๋ฅธ ๋ชจ๋“  ํ•ญ๋ชฉ ๋™์ผ) ๋‚ด์—์„œ ์ž‘์—…์ž๋Š” ํ•ญ์ƒ ์‹œ๊ฐ„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ–ˆ๊ณ  ๊ณ„์†ํ•ด์„œ ์˜๊ตฌ์ ์œผ๋กœ ๋‹ค์‹œ ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ์Šค๋ ˆ๋“œ์—์„œ ๊ถŒ์žฅ ์‚ฌํ•ญ์„ ๊ฐ€์ ธ์™€ ์™„๋ฒฝํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋Š” ๋‹ค์Œ์œผ๋กœ ์ „ํ™˜ํ–ˆ์Šต๋‹ˆ๋‹ค.

workers = 1
threads = 8
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

์ด๊ฒƒ์ด ์ด ์Šค๋ ˆ๋“œ์™€ ๊ด€๋ จ์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐ๋˜๋ฉด ์—ฌ๊ธฐ์—์„œ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค๋ฅธ ๊ณณ์— ๋‘๊ฒ ์Šต๋‹ˆ๋‹ค ;-)

๋ฒ ์ŠคํŠธ, ๋ณด๋ฆฌ์Šค

@tilgovi

์ด ์˜ค๋ฅ˜๋Š” arbiter.py, murder_workers ํ•ฉ๋‹ˆ๋‹ค. murder_workers ํ•จ์ˆ˜๋Š” SIG_QUEUE ๊ฐ€ ๋น„์–ด ์žˆ์„ ๋•Œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค(์˜ˆ: ์‹ ํ˜ธ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ๋™์•ˆ).

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋งค์ดˆ ์‹œ๊ฐ„ ์ดˆ๊ณผ์— ๋„๋‹ฌํ–ˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋‚จ์€ ์‹œ๊ฐ„์€ gevent ์ž‘์—…์ž๊ฐ€ ์ œ์–ด๋œ ๋ฌดํ•œ ๋ฃจํ”„์— ์žˆ๊ณ  self.alive ๊ฐ€ ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” self.notify ๋ฅผ ํ˜ธ์ถœํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ•ญ์ƒ 1์ดˆ ๋˜๋Š” 0์ดˆ์˜€์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๋Š” gunicorn์ด ๋งˆ์ง€๋ง‰ ํ™œ์„ฑ ์‹œ๊ฐ„์ด ๋ฐœ์ƒํ•œ ์‹œ๊ฐ„์„ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ murder_workers ํ•จ์ˆ˜์˜ TTL(Time to Live) ๊ฒ€์‚ฌ๊ฐ€ ์‹คํŒจํ•˜๋Š” ์œ ์ผํ•œ ๋ฐฉ๋ฒ•์€(์˜ˆ: ๋„ˆ๋ฌด ์˜ค๋ž˜ ์œ ํœด ์ƒํƒœ์˜€๋‹ค๊ณ  ํ•จ) gevent live ์†์„ฑ์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ฉ”์„œ๋“œ๊ฐ€ ์ด๋ฅผ ์ œ์–ดํ•ฉ๋‹ˆ๋‹ค.

handle_quit
handle_request (์ตœ๋Œ€ ์š”์ฒญ์ด ์ˆ˜์‹ ๋œ ๊ฒฝ์šฐ ๊ธฐ๋ณธ์ ์œผ๋กœ ์š”์ฒญ ์ˆ˜์˜ 2^64๋น„ํŠธ ๋˜๋Š” 32๋น„ํŠธ OS์ธ ๊ฒฝ์šฐ 2^32)
changed (ํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋œ ๊ฒฝ์šฐ ๋ฆฌ๋กœ๋”์—์„œ ํ˜ธ์ถœ๋จ)
handle_exit
handle_abort

์ด ๋ฉ”์„œ๋“œ๋Š” ์‹ ํ˜ธ์—์„œ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค.

handle_quit - SIGQUIT, SIGINT
handle_exit - SIGTERM
handle_abort - SIGABRT

๋”ฐ๋ผ์„œ ๋‚ด๊ฐ€ ๋ณผ ์ˆ˜์žˆ๋Š” ๋‘ ๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. ์•Œ๋ฆผ ๋ฉ”์„œ๋“œ๋Š” ๋ฃจํ”„ ์ค‘์— ํŒŒ์ผ์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  2. ์‹ ํ˜ธ๊ฐ€ ์ž˜๋ชป ์ „์†ก๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ€์žฅ ๊ฐ€๋Šฅ์„ฑ ์žˆ๋Š” ์›์ธ์€ 2๋ฒˆ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์‹ ํ˜ธ์˜ ์ฃผ์š” ์†Œ์Šค๋Š” ์ค‘์žฌ์ž ํŒŒ์ผ ๋‚ด์— ์žˆ์œผ๋ฉฐ ๋‹ค์Œ ์˜ˆ์™ธ์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

  • StopIteration
  • KeyboardInterrupt
  • HaltServer
  • Exception (์ฒ˜๋ฆฌ๋˜์ง€ ์•Š์€ ์˜ˆ์™ธ)

StopIteration ์˜ˆ์™ธ๊ฐ€ req = six.next(parser) ์˜ async.py ํŒŒ์ผ์—์„œ ํŠธ๋ฆฌ๊ฑฐ๋œ ๋ฒ”์ธ์ผ ๊ฐ€๋Šฅ์„ฑ์ด ๊ฐ€์žฅ ๋†’๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๋‹ค์Œ ๋ฉ”์†Œ๋“œ๋Š” parser.next()๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

Parser.next() ๋Š” ๋‹ค์Œ 2๊ฐ€์ง€ ์กฐ๊ฑด์—์„œ StopIteration ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

1. If the message indicates it should close:
    1. http Connection close (and keep-alive false)
    2. WSGI - request method not HEAD, response_length is none, and status code is > 200 (but not 204, or 304)
2. If self.mesg (Request message) is falsey

์˜๋„ํ•˜์ง€ ์•Š์€ ๋ฌธ์ œ์˜ ์›์ธ์ด ์ •ํ™•ํžˆ ๋ฌด์—‡์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์ง€๋งŒ ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ 62๊ฐœ์˜ ๋Œ“๊ธ€ ์ค‘ ์—ฌ๋Ÿฌ ์•ฑ๊ณผ ํ™˜๊ฒฝ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์กฐ์‚ฌํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๊ณ  ๋‹ค์‹œ ์—ด๊ฑฐ๋‚˜ ์ œ๋ชฉ์ด ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๋Š” ๊ฒฝ์šฐ , ์ž‘์—…์ž๊ฐ€ ์‹ฌ๊ฐํ•œ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋กœ ์ƒˆ๋กœ์šด ๊ธ€๋กœ๋ฒŒ ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ ๋‹ค์‹œ ์—ด๊ณ  ๋‹ค์Œ ์กฐํ•ฉ์„ ํ…Œ์ŠคํŠธํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ๋„์ปค ๋กœ์ปฌ
  • Classic Load Balancer๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AWS ๋„์ปค
  • Application Load Balancer๋กœ AWS ๋„์ปค

๋ˆ„๊ตฌ๋“ ์ง€ ์ด๊ฒƒ์„ ์žฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” repo๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๋„์›€์ด ๋  ๊ฒƒ์ด์ง€๋งŒ ์•„๋งˆ ์ด๋ฒˆ ์ฃผ๋ง์— ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฉฐ AWS๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋‚ด ์„ค์ •์€ NGINX -> Docker ์ปจํ…Œ์ด๋„ˆ(gevent ์ž‘์—…์ž๊ฐ€ ์žˆ๋Š” Gunicorn + Django)์ž…๋‹ˆ๋‹ค. Gunicorn์˜ ๊ธฐ๋ณธ ์‹œ๊ฐ„ ์ดˆ๊ณผ๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

ํŒ์ด ์žˆ๋‚˜์š”?

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

์•ˆ๋…•ํ•˜์„ธ์š” @davidmir ์ž…๋‹ˆ๋‹ค .
๋‚˜๋Š” ๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๊ณ  ์ž‘์—…์ž ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•ด๋„ ๋„์›€์ด๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋Š” ๋‹จ์ผ ๋™๊ธฐํ™” ์ž‘์—…์ž๋กœ ์ „ํ™˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํŠธ๋ฆญ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

workers = 1
threads = 8
worker_class = 'sync'
worker_connections = 1000
timeout = 30
keepalive = 2

๋ฒ ์ŠคํŠธ, ๋ณด๋ฆฌ์Šค

์œ„์—์„œ ์ผ๋ถ€ ์–ธ๊ธ‰ํ–ˆ์ง€๋งŒ ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋‚ด ์ž์‹ ์˜ ๋””๋ฒ„๊น…์„ ๋ช…ํ™•ํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์ด ์ค‘ ์ผ๋ถ€๋Š” ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ์ž‘์—…์ž ์ˆ˜๋ฅผ 1๋กœ ๋ณ€๊ฒฝํ•˜์—ฌ ํ•ด๊ฒฐ๋˜๋Š” ๊ฒฝ์šฐ.

๊ตฌ์„ฑ์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ•ญ๋ชฉ์ด ์žˆ๋Š” ๊ฒฝ์šฐ Docker์—์„œ ํŠนํžˆ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

workers = multiprocessing.cpu_count() * 2 + 1

๊ทธ๋Ÿฌ๋‚˜ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค. ๋™๊ธฐ ์ž‘์—…์ž๋Š” ์ž ์žฌ์ ์œผ๋กœ ๋ฌด๊ฑฐ์šด ์—ฌ๋Ÿฌ ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. CPU ์ˆ˜๋Š” ์‚ฌ์šฉํ•  ๋„์ปค ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ”„๋กœ๋น„์ €๋‹ํ•œ ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋จธ์‹ ์˜ ์ „์ฒด CPU ์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ œํ•œ๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ๋Œ€์‹  ์ž‘์—…์ž ์ˆ˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์‘์šฉ ํ”„๋กœ๊ทธ๋žจ๋งˆ๋‹ค ๋‹ค๋ฅด์ง€๋งŒ ํ•„์ž์˜ ๊ฒฝํ—˜์— ๋”ฐ๋ฅด๋ฉด ๋ฆฐ ๊ตฌ์„ฑ์—์„œ๋Š” ์ž‘์—…์ž๋‹น 256๋ฉ”๊ฐ€, ์•ˆ์ „ํ•˜๋ ค๋ฉด 512๋ฉ”๊ฐ€์ž…๋‹ˆ๋‹ค.

Classic ELB HTTPS => HTTP Gunicorn Sync Workers๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๊ฐ€์žฅ ์‰ฌ์šด ์ˆ˜์ •์€ ๊ธฐ๋ณธ ๋™๊ธฐํ™” ์ž‘์—…์ž ๋Œ€์‹  -k gevent ์ธ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์™„์ „ํžˆ ์ƒˆ๋กœ์šด Docker ์ปจํ…Œ์ด๋„ˆ(ALB ๋’ค์˜ ECS์—์„œ ํ˜ธ์ŠคํŒ…๋จ)์— ๋Œ€ํ•ด ์ด์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ๋‹ค์‹œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ๋ณด์•˜๊ณ  ์™„์ „ํžˆ ๋‹ค๋ฅธ(๊ทธ๋Ÿฌ๋‚˜ ๋Œ์ด์ผœ ๋ณด๋ฉด ๋ถ„๋ช…ํ–ˆ์–ด์•ผ ํ•˜๋Š”) ์†”๋ฃจ์…˜์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. CloudFormation์—์„œ ์ปจํ…Œ์ด๋„ˆ์— ๋” ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜์‹ญ์‹œ์˜ค. ์ฃผํ˜•.

์ž‘๋…„์— ์ด ๋ฌธ์ œ๋กœ ์–ด๋ ค์›€์„ ๊ฒช์—ˆ๊ณ  ์—ฐ๊ธฐ๊ฐ€ ๋‚˜๋Š” ์ด๊ธฐ์˜ ๊ทผ๋ณธ ์›์ธ์„ ์ฐพ์ง€ ๋ชปํ–ˆ์ง€๋งŒ ์˜ค๋Š˜ ๋ฐค ์ƒˆ ์ปจํ…Œ์ด๋„ˆ์—์„œ ๋ฐœ๊ฒฌํ–ˆ๊ณ  ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ํ• ๋‹นํ•œ ๋ชจ๋“  ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋จน๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ• ๋‹น์„ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฌ์ž ๋งˆ์ž ์ปจํ…Œ์ด๋„ˆ๋Š” ์ด ์˜ค๋ฅ˜๋ฅผ ๋˜์ง€๋Š” ๊ฒƒ์„ ๋ฉˆ์ท„์Šต๋‹ˆ๋‹ค.
https://github.com/hackoregon/civic-devops/issues/157

์—ฌ๊ธฐ์— ๋น„์Šทํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค.

while true:
      sleep(10)

์ž‘์—…์ž๊ฐ€ ์ฃฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์ด ์ฝ”๋“œ๊ฐ€ ์—†์œผ๋ฉด ๋ฐฐํฌ๋Š” ์ •์ƒ์ž…๋‹ˆ๋‹ค).
๊ทธ๊ฒƒ์€ ๋งค์šฐ ์ˆ˜์ˆ˜๊ป˜๋ผ์ž…๋‹ˆ๋‹ค. b/c sleep ๋Š” ์ด๋ฏธ ํ•˜ํŠธ๋น„ํŠธ๋ฅผ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด๋ฏธ gevent๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์ง€๋งŒ ๋„์›€์ด๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ƒ๊ฐ์ด ์žˆ๋Š” ์‚ฌ๋žŒ์ด ์žˆ๋Š”์ง€ ๊ถ๊ธˆํ•˜์‹ญ๋‹ˆ๊นŒ?

์ƒ˜ํ”Œ ์ถœ๋ ฅ:
[2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:521) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:522) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:523) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:524) [2018-06-16 16:00:16 +0000] [136] [CRITICAL] WORKER TIMEOUT (pid:525) [2018-06-16 16:00:16 +0000] [524] [INFO] Worker exiting (pid: 524) [2018-06-16 16:00:16 +0000] [521] [INFO] Worker exiting (pid: 521) [2018-06-16 16:00:16 +0000] [523] [INFO] Worker exiting (pid: 523) [2018-06-16 16:00:16 +0000] [522] [INFO] Worker exiting (pid: 522) [2018-06-16 16:00:16 +0000] [525] [INFO] Worker exiting (pid: 525) [2018-06-16 16:00:17 +0000] [531] [INFO] Booting worker with pid: 531 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [136] [DEBUG] 1 workers [2018-06-16 16:00:17 +0000] [532] [INFO] Booting worker with pid: 532 [2018-06-16 16:00:17 +0000] [533] [INFO] Booting worker with pid: 533 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [534] [INFO] Booting worker with pid: 534 /usr/local/lib/python3.6/site-packages/gunicorn/workers/ggevent.py:65: MonkeyPatchWarning: Monkey-patching ssl after ssl has already been imported may lead to errors, including RecursionError on Python 3.6. Please monkey-patch earlier. See https://github.com/gevent/gevent/issues/1016 monkey.patch_all(subprocess=True) [2018-06-16 16:00:17 +0000] [535] [INFO] Booting worker with pid: 535 [2018-06-16 16:00:17 +0000] [136] [DEBUG] 5 workers

์—ฌ๊ธฐ ๋ฌผ์„ ํ๋ฆฌ๊ฒŒ ํ•ด์„œ ๋ฏธ์•ˆํ•˜์ง€๋งŒ ๋‚ด ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์Šคํƒ์€ HTTP ELB > Nginx > gunicorn/gevent on EC2 ์ด๋ฉฐ ํ”„๋กœ์„ธ์Šค๋Š” circusd๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์ฐพ์€ ๋ฌธ์ œ๋Š” Elastic-apm์œผ๋กœ django ์•ฑ์„ ๊ณ„์ธกํ•œ ํ›„ HTTP ์ƒํƒœ ํ™•์ธ์ด ๊ฑฐ์˜ ์ฆ‰์‹œ ์‹คํŒจํ•˜๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  gunicorn์ด ๋ช‡ ์ดˆ ํ›„์— ์‘๋‹ตํ•˜์ง€ ์•Š๊ฒŒ ๋œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ์ƒํƒœ ํ™•์ธ์— ๋Œ€ํ•ด ๋ช‡ ๊ฐ€์ง€ ๋กœ์ปฌ wrk ๋ฒค์น˜๋งˆํฌ๋ฅผ ์‹œ๋„ํ–ˆ๋Š”๋ฐ ๋™๊ธฐํ™”๋Š” 1-5๋ช…์˜ ์ž‘์—…์ž์— ๋Œ€ํ•ด ์•ฝ 300rps๋ฅผ ์–ป์—ˆ์ง€๋งŒ gevent๋Š” 1rps๋ฅผ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค. apm์„ ๋„๋ฉด gevent๊ฐ€ ์ตœ๋Œ€ ์•ฝ 50rps๊นŒ์ง€ ์˜ฌ๋ผ๊ฐ€๊ณ  ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ๋ฌด์‹œํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜์ค€์œผ๋กœ ์ฆ๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

valgrind์—์„œ ์ด์ƒํ•œ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์„ ๋ฐœ๊ฒฌํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ gunicorn์˜ ๊ฒฝ์šฐ ์•ฝ 4MB, ์ž‘์—…์ž๋‹น ์•ฝ 40MB์ž…๋‹ˆ๋‹ค.

์–ด์จŒ๋“  gunicorn 19.6.0 > 19.9.0 ๋ฐ gevent 1.2.2 > 1.3.6 ์—…๋ฐ์ดํŠธํ•˜๋ฉด ELB ์ƒํƒœ ํ™•์ธ์ด ๋‹ค์‹œ ์•ˆ์ •์ ์ด๊ณ  ๋กœ์ปฌ์—์„œ ~300rps๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” APM ๋กœ๊ทธ์ธ์ด ์žˆ์„ ๋•Œ๊นŒ์ง€ gunicorn/gevent๋ฅผ ์˜๋„์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์šฐ์—ฐํ•œ ์ผ์„ ์ด‰๋ฐœํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. gevent๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ๋‹น์—ฐํžˆ ๊ฐ€์žฅ ํฐ ํ–ฅ์ƒ์„ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ gunicorn์„ ์—…๋ฐ์ดํŠธํ•˜๋ฉด 10% ์ •๋„ ๋” ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ ๊ฐ™์•˜์Šต๋‹ˆ๋‹ค.

์•„์ง ๋ณ€๊ฒฝ ๋กœ๊ทธ๋ฅผ ์ž์„ธํžˆ ์‚ดํŽด๋ณด์ง€ ์•Š์•˜์ง€๋งŒ ์œ ์ง€ ๊ด€๋ฆฌ์ž๊ฐ€ ๊ฐ€์žฅ ๊ฐ€๋Šฅ์„ฑ ์žˆ๋Š” ์›์ธ์„ ๋ฐํž ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์–ด์จŒ๋“ , gunicorn 19.6.0 > 19.9.0 ๋ฐ gevent 1.2.2 > 1.3.6์„ ์—…๋ฐ์ดํŠธํ•˜๋ฉด ๋‹ค์‹œ ํ™•๊ณ ํ•œ ELB ์ƒํƒœ ํ™•์ธ์ด ์ œ๊ณต๋˜๊ณ  ๋กœ์ปฌ์—์„œ ~300rps๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.... gevent ์—…๋ฐ์ดํŠธ๊ฐ€ ๊ฐ€์žฅ ํฐ ํ–ฅ์ƒ์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

์™€, ์ •๋ง ๋ฉ‹์ง€๋„ค์š”!

๋งˆ๊ฐ ๋ฌธ์ œ. ํ•œ๋™์•ˆ ํ™œ๋™์ด ์—†์Šต๋‹ˆ๋‹ค.

FWIW, ๋‚˜๋Š” ์—ฌ์ „ํžˆ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค @benoitc :-\

์žฅ๊ณ  2.1.5
๊ธฐ๋‹ˆ์ฝ˜ 19.8.1
์ œ๋ฒคํŠธ 1.2.2
5๊ฐœ์˜ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” AKS 1.15.7(ํ‘œ์ค€ B2 - 2๊ฐœ์˜ vcore ๋ฐ 2GB ๋ฉ”๋ชจ๋ฆฌ)
๊ฐ๊ฐ ๋‹ค์Œ์„ ํฌํ•จํ•˜๋Š” 3๊ฐœ์˜ ํฌ๋“œ/๋„์ปค ์ปจํ…Œ์ด๋„ˆ:

    spec:
      containers:
        - name: web-container
          command: ["newrelic-admin"]
          args: [
              "run-program",
              "gunicorn",
              "--limit-request-field_size=16380", # limit also specified in nginx
              "--workers=3", # (2 x vcpu) + 1. vcpu < limit defined in resources
              "-k=gevent",
              "-b=0.0.0.0:8000",
              "ourapp.wsgi",
              "--timeout 60",
              "--log-level=debug",
            ]
          resources:
            requests:
              memory: "200Mi"
              cpu: "250m"
            limits:
              memory: "3000Mi"
              cpu: "2000m"

EKS, Nginx ๋ฐ NLB์™€ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

@salmicrosoft @sinkr ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์—ด๊ณ  ์–ด๋–ค ์ผ์ด ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ํŒŒ์•…ํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๋กœ๊ทธ๋ฅผ ์ œ๊ณตํ•˜์„ธ์š”. ๋˜ํ•œ ๊ท€ํ•˜์˜ ์•ฑ์€ ๋ฌด์—‡์„ํ•ฉ๋‹ˆ๊นŒ? ๊ธด ์š”์ฒญ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

ECS Fargate์—์„œ ๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ์ง€๋งŒ Docker/gunicorn.conf.py์˜ ์ž˜๋ชป๋œ keepalive/timeout ์„ค์ •๊ณผ ๊ด€๋ จ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์—ฐ๊ฒฐ ์œ ์ง€(์„ค์ •๋˜์ง€ ์•Š์Œ)
์‹œ๊ฐ„ ์ดˆ๊ณผ=2

์ˆ˜์ •ํ•˜๊ธฐ ์ „์—๋Š” ๋กœ์ปฌ์—์„œ ์‹คํ–‰๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ECS Fargate์—์„œ๋Š” ์‹คํŒจํ–ˆ์ง€๋งŒ ์ด์ œ ๋‘ ํ™˜๊ฒฝ์—์„œ ๋ชจ๋‘ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰