AWS์ Ubuntu 14.04 LTS์์ ์คํ๋๋ ๋์ปค ์ด๋ฏธ์ง ๋ด์์ gunicorn 19.4.5๋ฅผ ์ฌ์ฉํ๋ฉด >1 ๋๊ธฐํ ์์ ์์ ๊ธฐ๋ณธ 30์ด ์ ํ ์๊ฐ์ผ๋ก ์คํํ ๋ ์์ ์ ์ ํ ์๊ฐ์ด ๊ณ์ ํ์๋ฉ๋๋ค. ์ด๊ฒ์ #588 ๋๋ #942์ ๊ด๋ จ์ด ์์ ์ ์์ง๋ง ์ด๊ฒ์ ์๋นํ ์ต์ ๋ฒ์ ์ gunicorn์ด๋ฏ๋ก ํ์คํ๊ฒ ๋งํ ์ ์์ต๋๋ค.
์ฌ๋ฌ ์คํ์ ๋ํ ์ ํฉ ์ฆ๊ฑฐ์ ๋ฐ๋ฅด๋ฉด ์์ ์ ์ค ํ ๋ช ์ด ์ํฅ์ ๋ฐ์ง ์์์ผ๋ฉฐ ๊ณ์ ์คํจํ๊ณ ๋ค์ ์์ํ๋ ๊ฒ์ N-1๋ช ์ ๋๋จธ์ง ์์ ์๋ฟ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ ์ด๊ฒ์ ์ ์ํ๋ ๋ช ๊ฐ์ง ๋ฐ์ดํฐ ํฌ์ธํธ๋ง ์ป์ ์ ์์์ผ๋ฏ๋ก ์ด๋ฅผ ๊ฐ๋ ฅํ ์ ํธ๋ก ๋ฐ์๋ค์ด์ง ๋ง์ญ์์ค.
์ ๊ฐ ํ์ธํ ์ฌํญ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
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)
hrmmm ์์ ๋ก๊ทธ์์ ์๊ฐ์ด ์ ๋ ๋ณํ์ง ์๋๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ๋ด๊ฐ ํ์ธํฉ๋๋ค
๊ฐ์ฌํฉ๋๋ค. ๊ฐ์ฌํฉ๋๋ค!
์ด ๋ฒ๊ทธ์ ์ํฅ์ ๋ฐ์ ์ ์์ต๋๋ค.
AWS(Elastic Beanstalk + EC2 Container Service)์ Docker ์ด๋ฏธ์ง ๋ด์์ gunicorn์ ์คํํ๊ณ ์์ต๋๋ค.
์ด๊ธฐํ ์งํ์ AWS์์ Docker ์ด๋ฏธ์ง๋ฅผ ์คํํ ๋๋ง ๋ฐ์ํ๊ธฐ ์์ํ๋ ์ง์์ ์ธ ์์
์ ์๊ฐ ์ด๊ณผ๊ฐ ์์ต๋๋ค.
๋์ผํ HTTP ์์ฒญ์ ๋๋ก๋ ๋ช ms, ๋๋ก๋ 20-30์ด๊ฐ ๊ฑธ๋ฆฝ๋๋ค. ์กด์ฌํ์ง ์๋ ํ์ด์ง, ์ธ์ฆ๋์ง ์์ ๋จ์ํ "Hello world" ๋ฌธ์์ด ํ์ด์ง ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ ์ฝ๋๋ฅผ ๊ฐ์ ธ์ค๋ ํ์ด์ง์ธ์ง๋ ์ค์ํ์ง ์์ต๋๋ค.
์ถ๊ฐ ์ธ๋ถ์ ๋ณด :
์ํฅ์ ๋ฐ์ง _์์_
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์ด ์ ํ ์๊ฐ์ผ๋ก ์คํํ ๋ ์์ ์ ์ ํ ์๊ฐ์ด ๊ณ์ ํ์๋ฉ๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ ์์ฒญํ ํ์๊ฐ ์์ผ๋ฉฐ ๋ก๊ทธ๋ฅผ ๋ชจ๋ํฐ๋งํ๊ธฐ๋ง ํ๋ฉด ์์ ์๊ฐ ์๊ฐ ์ด๊ณผ๋๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
ํ์ฌ 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์ด ์๋๋ผ ๋คํธ์ํฌ ์ฐ๊ฒฐ ์ค๋ฅ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๋ด ์ค์ ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
ํฅ๋ฏธ๋กญ๊ฒ๋ ์ฑ ์๋ฒ์์ 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
.
๋๋ฒ๊ทธ ๋ก๊ทธ์ ๋ฐ๋ฅด๋ฉด,
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
๋ฐ๋ผ์ ๋ด๊ฐ ๋ณผ ์์๋ ๋ ๊ฐ์ง ๊ฐ๋ฅํ ๋ฌธ์ ๊ฐ ์์ต๋๋ค.
๊ฐ์ฅ ๊ฐ๋ฅ์ฑ ์๋ ์์ธ์ 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๊ฐ์ ๋๊ธ ์ค ์ฌ๋ฌ ์ฑ๊ณผ ํ๊ฒฝ์์ ๋ณผ ์ ์์ต๋๋ค. ๋ ์กฐ์ฌํ ๊ฐ์น๊ฐ ์๋ค๊ณ ์๊ฐํ๊ณ ๋ค์ ์ด๊ฑฐ๋ ์ ๋ชฉ์ด ๋ง์์ ๋ค์ง ์๋ ๊ฒฝ์ฐ , ์์ ์๊ฐ ์ฌ๊ฐํ ์๊ฐ ์ด๊ณผ๋ก ์๋ก์ด ๊ธ๋ก๋ฒ ๋ฌธ์ ๋ฅผ ๋ง๋ญ๋๋ค.
์ด๊ฒ์ ๋ค์ ์ด๊ณ ๋ค์ ์กฐํฉ์ ํ ์คํธํด ๋ณด๊ฒ ์ต๋๋ค.
๋๊ตฌ๋ ์ง ์ด๊ฒ์ ์ฌํํ ์ ์๋ 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์์๋ ์คํจํ์ง๋ง ์ด์ ๋ ํ๊ฒฝ์์ ๋ชจ๋ ์ฌ๋ฐ๋ฅด๊ฒ ์๋ํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋์
gevent
์์ ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค.