์๋ ํ์ญ๋๊น,
์๋ฒ์์ ํด๋ผ์ด์ธํธ ์ธ์ฆ์ ์ ๋ณด๋ฅผ ๊ฒ์ํ ๋ค์ ๋ค์๊ณผ ๊ฐ์ด Flask ์ฑ์ ๊ฐ์ ธ์ค๋๋ก ์ฌ์ฉ์ ์ ์ ์์ ์๋ฅผ ์ค์ ํ๋ ค๊ณ ํฉ๋๋ค.
gunicorn_options.py:
import multiprocessing
import os
from mypackage.client_auth_worker import CustomSyncWorker
def config_dir():
return os.path.dirname(os.path.realpath(__file__))
bind = "0.0.0.0:8000"
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = CustomSyncWorker
timeout = 30
ca_certs = os.path.join(config_dir(), 'ca.cert.pem')
certfile = os.path.join(config_dir(), 'server.cert.pem')
keyfile = os.path.join(config_dir(), 'server.key.pem')
cert_reqs = 2
do_handshake_on_connect = True
custom_auth_worker.py:
from gunicorn.workers.sync import SyncWorker
class CustomSyncWorker(SyncWorker):
def handle_request(self, listener, req, client, addr):
subject = dict(client.getpeercert().get('subject')[0])
headers = dict(req.headers)
headers['X-USER'] = subject.get('commonName')
print(headers)
req.headers = list(headers.items())
super(CustomSyncWorker, self).handle_request(listener, req, client, addr)
๋ค์ ์์ธ๊ฐ ๊ณ์ ๋ฐ์ํฉ๋๋ค.
File "/Users/me/.virtualenvs/mypackage/lib/python3.5/site-packages/gunicorn/arbiter.py", line 162, in start
self.log.info("Using worker: %s", self.cfg.worker_class_str)
File "/Users/me/.virtualenvs/mypackage/lib/python3.5/site-packages/gunicorn/config.py", line 68, in __getattr__
raise AttributeError("No configuration setting for: %s" % name)
AttributeError: No configuration setting for: worker_class_str
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ๋ฌ ๊ฐ์ง๋ฅผ ์๋ํ์ต๋๋ค. ์๋ฅผ ๋ค์ด gunicorn_options.py
ํ์ผ์ worker_class_str
๋ฅผ ์ค์ ํ์ง๋ง ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋์ง ์์์ต๋๋ค. ๊ทธ๋ ์ค์ ํจํค์ง์ ์ฝ๋์ ํ๊ณ ์์ํ๊ณ ๋ด๊ฐ ์์ ๋ ๋ ๋ฐ๊ฒฌ gunicorn/arbiter.py
๋ผ์ธ ์ฃผ์ ํ์ผ : self.log.info("Using worker: %s", self.cfg.worker_class_str)
๋ชจ๋ ๋ฏธ์ธ ์๋ฒฝํ๊ฒ ์๋์์ CustomSyncWorker์ด ์๋ก๋๋๊ณ X-USER ํค๋์ ๋ชจ๋ ๊ฒ์ ์ค์ ํด์ผ ํ๋ ์์
์ ์ํํฉ๋๋ค.
๋ฒ๊ทธ์ธ๊ฐ์? ์๋๋ฉด ๋ด๊ฐ ๋ญ๊ฐ ํฌ๊ฒ ์๋ชปํ๊ณ ์์ต๋๊น? ๋๋ ์ผ์ ๊ฐ์ ๋ก ์คํํ๊ธฐ ์ํด ๋ก์ปฌ์์ ์ฝ๋๋ฅผ ์์ ํ๋ ์ผ์ ์ค์ค๋ก ๋ ๋งก์์๋ ์ ๋๋ค๊ณ ์๊ฐํฉ๋๋ค...
worker_class
๋ฌธ์์ด์ ์ ๋ฌํด์ผํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋์ ๋ณํ
worker_class = CustomSyncWorker
์๊ฒ
worker_class = 'mypackage.client_auth_worker.CustomSyncWorker'
๋น์ ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ด๊ฒ์ ์ด๋ฏธ http://docs.gunicorn.org/en/stable/settings.html#worker -class์ ๋ฌธ์ํ๋์ด ์์ต๋๋ค.
์ ํ์ ์ผ๋ก Gunicorn์ gunicorn.workers.base.Worker์ ํ์ ํด๋์ค์ ๋ํ Python ๊ฒฝ๋ก๋ฅผ ์ ๊ณตํ์ฌ ์์ ์ ์์ ์๋ฅผ ์ ๊ณตํ ์ ์์ต๋๋ค. ์ด ๋์ฒด ๊ตฌ๋ฌธ์ gevent ํด๋์ค์ธ gunicorn.workers.ggevent.GeventWorker๋ฅผ ๋ก๋ํฉ๋๋ค.
๋ฌผ๋ก ๋ ๋์ ์ ์์ด ์์ผ๋ฉด ๋ฌธ์๋ฅผ ํญ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
์ ๊ณ ๊ฐ์ฌํฉ๋๋ค!
๋๋ ๊ทธ๊ฒ์ ์๋ํ์ง๋ง ์๋ํ์ง ์์๋ค๊ณ ์๊ฐํ์ง๋ง ํ์คํ์ง ์์ผ๋ฉฐ ๋ฌธ์์ด์ ๋ค๋ฅด๊ฒ ์์ฑํ์ ์ ์์ต๋๋ค(์: "mypackage.client_auth_worker:CustomSyncWorker"
ํ์). ์ค๋ ๋์ค์ ์ง์ ๊ฐ๋ฉด ํ์ธํด๋ด์ผ๊ฒ ๋ค์.
๊ทธ ์ธ์๋ ๋๋ ๊ทธ ๋ฌธ์๋ฅผ ๋ณด์๊ณ ๊ทธ๊ฒ์ด ๋ด๊ฐํด์ผ ํ ์ผ์ธ์ง ๋ช ํํ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฌธ์ ๋๋ ์ ์ด๋ ๋ค๋ฅธ ๊ณณ (์ ์ ํ๋ค๊ณ ์๊ฐํ๋ ๊ณณ)์ ์ง์ ์ ์ธ ์๋ฅผ ๋ฃ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํ์ด์ฌ ๊ตฌ์ฑ ํ์ผ. ๋๋ ๋ง์ ์ํ์ฐฉ์ค๋ฅผ ๊ฒช์ผ๋ฉด์ ๊ฒฐ๊ณผ์ ์ผ๋ก ์ถ๋ ฅ๋ฌผ์ ์ฃผ์ ์ฒ๋ฆฌํ ํ ๊ฒ์ํ ์์ ๋ฒ์ ์ ์ป๊ฒ ๋์์ต๋๋ค.
๋๋ฌด ๋นจ๋ฆฌ ๋์์ ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค!
ํ์ธํ์ต๋๋ค. ํจ๊ณผ๊ฐ ์์์ต๋๋ค. ๋์ ์ค์ ๊ณ ๋ง์!
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
worker_class
๋ฌธ์์ด์ ์ ๋ฌํด์ผํ๋ค๊ณ ์๊ฐํฉ๋๋ค. ๊ทธ๋์ ๋ณํ์๊ฒ
๋น์ ์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ ๋๋ค.