Django Daphne ์ ASGI๋ฅผ ์ง์ํ๊ธฐ ์ํด ๊ฐ๋ฐ ์ค์ด์ง๋ง Daphne ์๋ฒ๋ ๋งค์ฐ ์๋กญ๊ณ ์์ง ํ๋ก๋์ ์ ์ ํฉํ์ง ์์ต๋๋ค(์: SSL ์ง์ ์์, ์ฑ์ ๋ฌธ์ ).
์ํํ WSGI/ASGI ์ฌ์ฉ์ ํ์ฉํ๊ธฐ ์ํด Gunicorn์ ASGI ์ง์ ์ ์ถ๊ฐํ๋ ๋ฐ ๊ด์ฌ์ด ์์ต๋๊น?
@arcivanov ์ด ํ๋กํ ์ฝ์ ๋ํด ์ํํด์ผ ํ ์์ ์ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. :)
์ด ํฐ์ผ์ ์ต๋ํ ๋นจ๋ฆฌ ์ ๋ฐ์ดํธํฉ๋๋ค.
์ด๋ค ์ ๋ฐ์ดํธ?
@benoitc @berkerpeksag ์ ๋๋ ๊ทธ๊ฒ์ ๋ํด ์ด๋ฉ์ผ๋ก ์ฑํ ํ์ต๋๋ค. ์์ง ๋ด๊ฐ ์๋ ์์ ์ด ์์๋์ง ์์์ต๋๋ค. ๋๋ ์์ง ASGI์ ๋ํด ๋ ๋ง์ด ์ฝ์ ์๊ฐ์ด ์์๊ธฐ ๋๋ฌธ์ ์ด๊ฒ์ ๊ตฌํํ๋ ๊ฒ์ด ์ผ๋ง๋ ๋ณต์กํ ์ง ์ง์ํ ์ ์์ต๋๋ค. ๋๊ตฐ๊ฐ๊ฐ ์ด๋ฅผ ์ํด ์์ ์ ๊ธฐ์ฌํ๊ณ ์ถ๋ค๋ฉด ์ด์ ์ ์ผ๋ก ๋๊ณ ํ ๋ก ํ๊ณ ๊ฒํ ํ ๊ฒ์ ๋๋ค.
์ด์จ๋ ์๋ฒ์ ๋ํด ํจ์ฌ ๋ ์ดํดํ๊ธฐ ์ํด ASGI ์ฌ์์ ์ ๊ฒํ๋ ์ค์ด๋ฏ๋ก ์๋ฃ๋ ๋๊น์ง ๋ฌด์์ด๋ ํ๋ ๊ฒ์ ๋ํด ์ฃผ์ํ ๊ฒ์ ๋๋ค(์ฌ๊ธฐ์ ์ ์ฌ์์ด ์ด์ ์์ฑ ์ค์ด์ง๋ง ์ต์ข ์ ์ธ ๊ฒ์ ์๋๋๋ค: http:// /channels.readthedocs.io/en/2.0/asgi.html - ๊ธฐ๋ณธ์ ์ผ๋ก WSGI์ ํจ์ฌ ๋น์ทํจ)
@andrewgodwin ๋ฉ์ง asgi์ ํจ๊ป gunicorn์ ์๋ํด๋ณด๊ณ ์ถ์ด ์ฐธ์ ์ ์์ต๋๋ค.
@andrewgodwin ASGI ์ํ๋ ๋ฌด์์ ๋๊น?
๋๋ ์ต๊ทผ์ ASGI ์ฑ์ ํ ์คํธํ๋ ค๊ณ ์๋ํ๊ณ ์ฌ๊ธฐ์ ๋ด๊ฐ ์ป์ ๊ฒ์ด ์์ต๋๋ค.
import json
def app(scope):
async def channel(receive, send):
message = await receive()
if scope['method'] == 'POST':
response = message
else:
response = scope
await send({
'type': 'http.response.start',
'status': 200,
'headers': [
[b'Content-Type', b'application/json'],
],
})
await send({
'type': 'http.response.body',
'body': json.dumps(response, default=bytes.decode).encode(),
})
await send({
'type': 'http.disconnect',
})
return channel
> daphne app:app
2018-03-31 22:28:10,823 INFO Starting server at tcp:port=8000:interface=127.0.0.1
2018-03-31 22:28:10,824 INFO HTTP/2 support enabled
2018-03-31 22:28:10,824 INFO Configuring endpoint tcp:port=8000:interface=127.0.0.1
2018-03-31 22:28:10,825 INFO Listening on TCP address 127.0.0.1:8000
127.0.0.1:43436 - - [31/Mar/2018:22:28:17] "GET /" 200 347
127.0.0.1:43440 - - [31/Mar/2018:22:28:22] "POST /" 200 43
127.0.0.1:43446 - - [31/Mar/2018:22:28:42] "POST /" 200 54
> http -b get :8000/
{
"type": "http"
"http_version": "1.1",
"method": "GET",
"path": "/",
"query_string": "",
"root_path": "",
"scheme": "http",
"headers": [
["host", "localhost:8000"],
["user-agent", "HTTPie/0.9.9"],
["accept-encoding", "gzip, deflate"],
["accept", "*/*"],
["connection", "keep-alive"]
],
"client": ["127.0.0.1", 43360],
"server": ["127.0.0.1", 8000],
}
> http -b -f post :8000/ foo=bar
{
"body": "foo=bar",
"type": "http.request"
}
> http -b -j post :8000/ foo=bar
{
"body": "{\"foo\": \"bar\"}",
"type": "http.request"
}
@sirex ASGI๋ ์ด์ ์์ ์ ์ ๋๋ค. daphne์ด ์ฌ์์ ์ค์ํ๊ฑฐ๋ ์ค์ํ์ง ์๋๋ค๊ณ ๋งํ๋์ง ์ ๋ชจ๋ฅด๊ฒ ์ต๋๋ค.
django์ ๋งํฌ๊ฐ ASGI "์ฌ์"์ ๋ํ ๋ง์ง๋ง ๋งํฌ์ ๋๊น, ์๋๋ฉด ํ๋ฆ์ ์ค๋ช ํ๋ ๋ ๋ง์ ๊ฒ์ด ์์ต๋๊น?
@andrewgodwin ์ ๋ Daphne์ด ASGI๋ฅผ ์ง์ํ๋ค๋ฉด ASGI๊ฐ ๋ค๋ฅธ ํ๋ ์์ํฌ/์๋ฒ๋ฅผ ์ฑํํ ์ค๋น๊ฐ ๋์ด ์์ด์ผ ํ๋ค๋ ๊ฒ์ ์์ฐํ๋ ค๊ณ ํ์ต๋๋ค.
@benoitc ๋ ๊ฐ์ ASGI ์ฌ์ ํ์ด์ง๊ฐ ์์ต๋๋ค.
https://github.com/django/asgiref/blob/master/specs/asgi.rst - ์ผ๋ฐ ASGI ์ฌ์.
https://github.com/django/asgiref/blob/master/specs/www.rst - HTTP ๋ฐ WebSockets ํ๋กํ ์ฝ๊ณผ WSGI์์ ํธํ์ฑ์ ์ค๋ช ํ๋ ์ฌ์์ ๋๋ค.
@sirex ๊ฐ์ฌํฉ๋๋ค. ์ด๋ฌํ ์ฌ์์ ๊ตฌํ์ ๊ดํ ํ ๊ทธ๋ค์ง ๋์์ด ๋์ง ์์ต๋๋ค.
์ด์จ๋ ๋๋ ๊ด์ฐฎ์ https://channels.readthedocs.io/en/latest/ ๋ฅผ ์ฐพ์์ต๋๋ค. ๋๋ pep๋ฅผ ์ ํธํ๋ค๊ณ ์๊ฐํ์ง๋ง python 2 ์ง์์ ์ ๊ฑฐํ์๋ง์ asgi๋ฅผ ์ง์ํ๋ ๊ฒ์ ์ ์ํ ์ ์์ต๋๋ค.
btw ํด๋น ํ ๋ก ๊ณผ ๊ด๋ จ์ด ์์ผ๋ฏ๋ก ๋ง์ง๋ง ๋๊ธ์ ์ญ์ ํ์ต๋๋ค.
ASGI๋ฅผ PEP๋ก ๋ง๋ค๊ธฐ ์ํด ์์ง์ด์ง ์์๋๋ฐ, ๋จผ์ ์ถฉ๋ถํ ์ผ๋ฐ ์ง์์ด ์๋์ง ํ์ธํ๊ณ ์ถ์๊ธฐ ๋๋ฌธ์ ๋๋ค(๊ทธ๋ฆฌ๊ณ ๊ทธ ๊ณผ์ ์๋ ๋ง์ ์๊ฐ๊ณผ ๋ ธ๋ ฅ์ด ํ์ํฉ๋๋ค). ๊ทธ๋ฌ๋ ๊ทธ๊ฒ์ด ์๋์ด๊ณ ํ๋์ฒ๋ผ ์์ฑ๋์ด์ผ ํฉ๋๋ค.
python 2 ์ง์์ ์ ๊ฑฐํ์๋ง์ asgi๋ฅผ ์ง์ํ๋ ๊ฒ์ ์ ์ํ ์ ์์ต๋๋ค.
๊ตฌํ์ ๋ํด ์๊ฐํ๊ธฐ ์์ํ๋ค๋ฉด gunicorn, uvloop ๋ฐ httptools๋ฅผ ํจ๊ป ์ ์ฐฉํ๋ uvicorn ์ผ๋ก ์์ํ๋
(๊ทธ๋ฐ ๋ค์ gunicorn์ด ์ ๊ณตํ๋ ํ๋ก์ธ์ค ๋ชจ๋ํฐ๋ง ๋ฑ์ด ์์ด uvicorn์ด ๋ ์ต์ํ์ ์ต์ ์ด ๋๋ ๊ฒ์ด ์ข์ ์ ์์ต๋๋ค.)
ASGI ์ฌ์ ๋ฌธ์๋ ์ด์ https://asgi.readthedocs.io/en/latest/์์ ์ฌ์ฉํ ์ ์์ต๋๋ค
์ข์, ์ง๊ธ ์ด๊ฒ์ ๋ฎ์ผ์ญ์์ค. (ํ์ฌ ์์ ์ ํด๋์ค๋ก.)
Uvicorn 0.2๋ ๋ ์ด์ ์ง์ ์คํ์ ์ํด gunicorn์ ์์กดํ์ง ์์ง๋ง ASGI ์ฑ์ ์คํํ๊ธฐ ์ํ ๋ ๊ฐ์ gunicorn ์์ ์ ํด๋์ค๋ฅผ ํฌํจํฉ๋๋ค.
๋ก์ปฌ ๊ฐ๋ฐ์ ๋๋ ํ๋ก์ธ์ค ๊ฐ๋ ์ ๋ํด ์ถฉ๋ถํ ์ ๊ฒฝ ์ฐ์ง ์๋ ๊ฒฝ์ฐ์๋ uvicorn์ ์ง์ ์คํํ ์ ์์ต๋๋ค. ํ๋ก๋์ ์ ์ํด ๊ธฐ๋ณธ ์ต์ ์ผ๋ก gunicorn ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ํํฉ๋๋ค.
http://www.uvicorn.org/#running-with-gunicorn
uvloop ๋ฐ httptools๋ฅผ ์ฌ์ฉํ์ฌ gunicorn์์ ASGI ์ฑ์ ์คํํฉ๋๋ค.
gunicorn app:App -w 4 -k uvicorn.workers.UvicornWorker
asyncio ๋ฐ h11(pypy ํธํ์ฑ์ ์ํด)์ ์ฌ์ฉํ์ฌ gunicorn์์ ASGI ์ฑ์ ์คํํฉ๋๋ค.
gunicorn app:App -w 4 -k uvicorn.workers.UvicornH11Worker
ํ๋กํ ์ฝ ๊ตฌํ ์ค ํ๋๋ฅผ ํต์ฌ gunicorn ํจํค์ง๋ก ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ๊ฒฝ์ฐ ์ด๋ฅผ ๊ณ ๋ คํ๋ ๋ฐ ๋งค์ฐ ๊ฐ๋ฐฉ์ ์ ๋๋ค.
์ด์ gunicorn
์ด python
2
๋ ์ด์ ์ง์ํ์ง ์์ผ๋ฏ๋ก ๊ธฐ์ ์ ์ผ๋ก ASGI
์ง์์ ์ถ๊ฐํ ์ ์์ต๋๋ค.
@tomchristie ๋๋ ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง์ ๊ด์ฌ์ด ์์ต๋๋ค. ๋์์ผ๋ก ํ๋กํ ์ฝ์ ๋ณ๋์ ํจํค์ง๋ก ์ถ์ถํ ์ ์์ต๋๊น?
๋๋ ๊ทธ๊ฒ์ด ์ด๋ป๊ฒ ์๊ฒผ๋์ง์ ๊ด์ฌ์ด ์์ต๋๋ค. ๋์์ผ๋ก ํ๋กํ ์ฝ์ ๋ณ๋์ ํจํค์ง๋ก ์ถ์ถํ ์ ์์ต๋๊น?
h11 ๋ฐ/๋๋ httptools ํ๋กํ ์ฝ์ ๋ํด uvicorn
์ ์์กดํ๋ gunicorn์ ์์
์ ํด๋์ค ์ค ํ๋๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋๋ ์ฌ๊ธฐ์์ ๊ตฌํ์ ๋ณต์ ํ์ญ์์ค.
h11
์ข
์์ฑ์ด ์๋ Gunicorn ๋ด์ฅ ASGI HTTP ์ง์์ ์ ๊ณตํ๊ธฐ ์ํด ๊ตฌํ์ ์ ํ๋ ๋ถ๋ถ์ ๋ณต์ ํ๋ ๊ฒ์ด ์ข์ ๊ธฐ์ค์ด ๋ ์ ์์ต๋๊น?
ํ๋กํ ์ฝ์ ๋ณ๋์ ํจํค์ง๋ก ์ถ์ถํ ์ ์์ต๋๊น?
uvicorn
์์ ์ถ์ถํ ๋ด์ฉ์ด ๋ง์ง ์์ต๋๋ค. click
ํ๊ณ argparse๋ฅผ ์ฌ์ฉํ๊ณ setup.py ์ข
์์ฑ์ ์ฝ๊ฐ ์กฐ์ ํ๋ฉด ๋ค์ํ ์ต์
๊ณผ ํจ๊ป ํ๋ ์ข
์์ฑ์ด 0์ด ๋ฉ๋๋ค. ๋ค๋ฅธ HTTP ๊ตฌํ, WS ๊ตฌํ, ์ด๋ฒคํธ ๋ฃจํ.
๋ฌด์์ ์ค์นํ ์ง ์๋ ค์ฃผ๋ ์คํ ์์ ์์ธ Gunicorn์ ์ถ๊ฐ ์ข ์์ฑ์ ์ถ๊ฐํ๋ ๊ฒ์ ์๋ฏธํ๋ , ๋ฌธ์ํ ๋๋ ๊ธฐํ ๋ฌด์์ด๋ ์ผ๋ฅ ASGI ์ง์์ ์ํฉ๋๋ค.
์, ๋ถํํฉ๋๋ค. gunicorn์์ daphne์ผ๋ก ์ ํํ๋ ค๊ณ ํฉ๋๋ค .. gunicorn์ด asgi๋ฅผ ์ง์ํ ์ ์๋ค๋ฉด
๊ทธ๋ ๊ฒ ํ๋ฉด ์๊ฐ์ ๋ง์ด ์ ์ฝํ ์ ์์ต๋๋ค.
@japrogramer http://www.uvicorn.org/#running -with -gunicorn
Django 3.0(2019๋
12์ ์ถ์ ์์ )์ ๊ธฐ๋ณธ์ ์ผ๋ก ASGI๋ฅผ ์ง์ ํ๋ฏ๋ก gunicorn
์์ ์ง์ ์ง์ํ๋ ๋ ๋ค๋ฅธ ํฐ ์ด์ ๊ฐ ๋ฉ๋๋ค. ์ถ์๋ ํ ์ฌ์ฉ์์ ๊ด์ฌ์ด ํฌ๊ฒ ์ฆ๊ฐํ ๊ฒ์
๋๋ค.
@johnthagen ํ์ดํ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๋ ์ฝ๊ฐ์ ํฐ์ผ์ ์ ๋ฆฌํ๊ณ ์์ํ๊ธฐ ์ ์ ์ด๋ฒ ๋ฌ์ ๋ฆด๋ฆฌ์คํด์ผํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
์ข์, ์ง๊ธ ์ด๊ฒ์ ๋ฎ์ผ์ญ์์ค. (ํ์ฌ ์์ ์ ํด๋์ค๋ก.)
Uvicorn 0.2๋ ๋ ์ด์ ์ง์ ์คํ์ ์ํด gunicorn์ ์์กดํ์ง ์์ง๋ง ASGI ์ฑ์ ์คํํ๊ธฐ ์ํ ๋ ๊ฐ์ gunicorn ์์ ์ ํด๋์ค๋ฅผ ํฌํจํฉ๋๋ค.
๋ก์ปฌ ๊ฐ๋ฐ์ ๋๋ ํ๋ก์ธ์ค ๊ฐ๋ ์ ๋ํด ์ถฉ๋ถํ ์ ๊ฒฝ ์ฐ์ง ์๋ ๊ฒฝ์ฐ์๋ uvicorn์ ์ง์ ์คํํ ์ ์์ต๋๋ค. ํ๋ก๋์ ์ ์ํด ๊ธฐ๋ณธ ์ต์ ์ผ๋ก gunicorn ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ฌธ์ํํฉ๋๋ค.
http://www.uvicorn.org/#running-with-gunicorn
uvloop ๋ฐ httptools๋ฅผ ์ฌ์ฉํ์ฌ gunicorn์์ ASGI ์ฑ์ ์คํํฉ๋๋ค.
asyncio ๋ฐ h11(pypy ํธํ์ฑ์ ์ํด)์ ์ฌ์ฉํ์ฌ gunicorn์์ ASGI ์ฑ์ ์คํํฉ๋๋ค.
ํ๋กํ ์ฝ ๊ตฌํ ์ค ํ๋๋ฅผ ํต์ฌ gunicorn ํจํค์ง๋ก ๊ฐ์ ธ์ค๊ณ ์ ํ๋ ๊ฒฝ์ฐ ์ด๋ฅผ ๊ณ ๋ คํ๋ ๋ฐ ๋งค์ฐ ๊ฐ๋ฐฉ์ ์ ๋๋ค.