$30 off During Our Annual Pro Sale. View Details »

ASGI(非同期サーバゲートウェイインターフェース)の概要

 ASGI(非同期サーバゲートウェイインターフェース)の概要

PyCon JP 2020 カンファレンス 資料です。

Junya Fukuda

August 31, 2020
Tweet

More Decks by Junya Fukuda

Other Decks in Programming

Transcript

  1. "4(*ʢඇಉظαʔόήʔτ΢ΣΠ
    ΠϯλʔϑΣʔεʣͷ֓ཁ
    Junya Fukuda
    PyCon JP 2020

    View Slide

  2. 썡쎕썟썷쎣쎟
    •෱ా ൏໵ʢJunya Fukudaʣʢ@JunyaFffʣ
    •גࣜձࣾ೔ຊγεςϜٕݚʢJSLʣॴଐ
    •PyCon JP 2020 Gold Sponser ʢΦϯϥΠϯϒʔεʹ΋༡ͼʹ͖ͯͶʣ
    •GEEKLAB.NAGANO
    •࠷ۙϚΠϯΫϥϑτͰখֶੜ޲͚Youtube഑৴࢝ΊΔ ΪʔΫϥϘ௕໺ϚΠΫϥ

    View Slide

  3. ຊ쏅쏍쏁쏱쏽쎅ྲྀ쎣
    •HTTPͷྺ࢙Λ؆୯ʹৼΓฦΓ
    •WSGIͷྺ࢙
    •ASGIͷ࢓༷ͷ͸ͳ͠ʢΫϥΠΞϯτͱαʔόͷίʔυΛަ͑ͯʣ
    •ASGIΛऔΓר͘ঢ়گ

    View Slide

  4. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵
    •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

    View Slide

  5. •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI
    쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵

    View Slide

  6. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵
    •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

    View Slide

  7. 쏬쏋쏣썗쏁쏱쏽썿쎾썗쏵
    •ASGI४ڌͷαʔό΍ϑϨʔϜϫʔΫʹ;Εͯ΋Β͏͖͔͚ͬʹͳΕ͹ʂ
    •ͪΐͬͱؾʹͳΔ͚ͲΑ͘෼͔Βͳ͍ଘࡏͷASGI

    View Slide

  8. Ωʔϫʔυ

    View Slide

  9. Ωʔϫʔυ ໰͍

    View Slide

  10. 쎷썗쏹썗쏓

    View Slide

  11. 쎷썗쏹썗쏓
    ಉظ

    View Slide

  12. ಉظ ඇಉظ
    쎷썗쏹썗쏓

    View Slide

  13. ಉظ ඇಉظ
    쎷썗쏹썗쏓
    ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε
    "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

    View Slide

  14. 쎷썗쏹썗쏓
    ಉظ ඇಉظ PEP

    View Slide

  15. 쎷썗쏹썗쏓
    ಉظ ඇಉظ PEP
    1ZUIPO&OIBODFNFOU1SPQPTBM
    1ZUIPOͷػೳڧԽͷఏҊ

    View Slide

  16. ໰썛

    View Slide

  17. ໰썛
    ඇಉظαʔόͱ͸ʁ
    ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε
    "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

    View Slide

  18. ·ͣ͸͡Ίʹ

    View Slide

  19. )551쎂썻썛썽쎅썡썬쎠썛
    •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ

    View Slide

  20. )551쎂썻썛썽쎅썡썬쎠썛
    •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ
    •HTTP/1.1 •HTTP/2 •HTTP/3

    View Slide

  21. )551쎂썻썛썽쎅썡썬쎠썛
    •ࠓن֨Խ͞Ε͍ͯΔͷ͸HTTPͷόʔδϣϯ͸ʁ
    •HTTP/1.1 •HTTP/2 •HTTP/3

    View Slide

  22. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ
    •HTTP/1.0 •HTTP/2 •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9 •HTTP/1.1

    View Slide

  23. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ

    View Slide

  24. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ

    View Slide

  25. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ

    View Slide

  26. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999 2015
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ

    View Slide

  27. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999 2015
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ
    ύϑΥʔϚεͷ޲্ʹϑΥʔΧε

    View Slide

  28. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999 2015
    2020೥ϒϥ΢βͰରԠ࢝·Γͩ͢
    •HTTPͷඪ४ԽΛ࣌ܥྻʹ

    View Slide

  29. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999 2015
    •WebSocket
    •֦ுػೳ

    View Slide

  30. )551쎂썻썛썽쎅썡썬쎠썛
    •HTTP/1.0
    •HTTP/2
    •HTTP/3
    1990 2000 2010 2020
    •HTTP/0.9
    •HTTP/1.1
    1997 1999 2015
    •WebSocket
    2011
    •WebSocketͷొ৔ʢRFC6455ʣ

    View Slide

  31. 84(*
    •WSGIͷొ৔
    •HTTP/2
    2000 2010 2020
    •HTTP/1.1
    1999 2015
    •WebSocket
    2011 2016

    View Slide

  32. 84(*
    •WSGIͷొ৔
    •HTTP/2
    2000 2010 2020
    •HTTP/1.1
    1999 2015
    •WebSocket
    2011
    WSGI
    2003 2016

    View Slide

  33. "4(*
    •ASGIͷొ৔
    •HTTP/2
    2000 2010 2020
    •HTTP/1.1
    1999 2015
    •WebSocket
    2011
    WSGI
    2003 2016

    View Slide

  34. "4(*
    •ASGIͷొ৔
    •HTTP/2
    2000 2010 2020
    •HTTP/1.1
    1999 2015
    •WebSocket
    2011
    WSGI
    2003 2016
    ASGI

    View Slide

  35. 84(*"4(*쎅쎿쏧썗쏒
    •WSGI͸HTTP1.1Λαϙʔτ
    •ASGI͸HTTP/1.1͔ΒWebSocketɺHTTP/2
    •HTTP/2
    2000 2010 2020
    •HTTP/1.1
    1999 2015
    •WebSocket
    2011
    WSGI
    2003 2016
    ASGI

    View Slide

  36. Ͱ͸·ͣ͸84(*ͷ࿩

    View Slide

  37. ಉظ

    View Slide

  38. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ

    View Slide

  39. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    ΫϥΠΞϯτ

    View Slide

  40. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    ΫϥΠΞϯτ 8FCαʔό

    View Slide

  41. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    ΫϥΠΞϯτ 8FCαʔό
    ΞϓϦέʔγϣϯ
    ϑϨʔϜϫʔΫ

    View Slide

  42. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    ΫϥΠΞϯτ 8FCαʔό
    ΞϓϦέʔγϣϯ
    ϑϨʔϜϫʔΫ

    View Slide

  43. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    ΫϥΠΞϯτ 8FCαʔό
    ΞϓϦέʔγϣϯ
    ϑϨʔϜϫʔΫ

    View Slide

  44. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    •2003೥ʹPEP 333 ʢ 2010೥ PEP 3333 Python3ରԠʣ

    View Slide

  45. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    •2003೥ʹPEP 333 ʢ 2010೥ PEP 3333 Python3ରԠʣ
    IUUQTXXXQZUIPOPSHEFWQFQTQFQ

    View Slide

  46. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    •2003೥ʹPEP 333 ʢ 2010೥ PEP 3333 Python3ରԠʣ
    IUUQTXXXQZUIPOPSHEFWQFQTQFQ

    View Slide

  47. 84(*
    •WSGIʢWeb Server Gateway Interfaceʣͷུ
    •Type͸ʮInformationalʯ
    •2003೥ʹPEP 333 ʢ 2010೥ PEP 3333 Python3ରԠʣ
    ΫϥΠΞϯτ 8FCαʔό
    ΞϓϦέʔγϣϯ
    ϑϨʔϜϫʔΫ

    View Slide

  48. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢
    •౰࣌ɺWeb Framework͕ᷓΕ͍ͯͨ
    •Zope, Quixote, Webware, SkunkWeb, PSO, and Twisted Web

    View Slide

  49. 84(*쎅໨ࢦ썮썶쎾썗쏵
    “Python͸ݱࡏɺZope, Quixote, Webware, SkunkWeb, PSO,
    Twisted WebͳͲɺଟछଟ༷ͳWebΞϓϦέʔγϣϯϑϨʔϜ
    ϫʔΫΛތ͍ͬͯ·͢ɻWebϑϨʔϜϫʔΫͷબ୒͸࢖༻Մೳͳ
    Webαʔόʔͷબ୒Λ੍ݶ͠ɺͦͷٯ΋ಉ༷Ͱ͋ΔͨΊɺ͜ͷ෯
    ޿͍બ୒ࢶ͸৽͍͠PythonϢʔβʔʹͱͬͯ໰୊ʹͳΔՄೳੑ͕
    ͋Γ·͢ɻ”
    - PEP 333 https://www.python.org/dev/peps/pep-0333/#rationale-and-goals

    View Slide

  50. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢
    WebαʔόA ϑϨʔϜϫʔΫA
    ϑϨʔϜϫʔΫB
    ϑϨʔϜϫʔΫC
    ϑϨʔϜϫʔΫD
    WebαʔόB
    WebαʔόC
    WebαʔόD

    View Slide

  51. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢
    84(*
    WebαʔόA
    WebαʔόB
    WebαʔόC
    WebαʔόD
    ϑϨʔϜϫʔΫA
    ϑϨʔϜϫʔΫB
    ϑϨʔϜϫʔΫC
    ϑϨʔϜϫʔΫD

    View Slide

  52. Server Application
    84(*ॲཧ쎅ྲྀ쎣

    View Slide

  53. Server Application
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  54. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  55. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  56. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  57. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME

    View Slide

  58. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME

    View Slide

  59. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME
    ཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

    View Slide

  60. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']

    View Slide

  61. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']

    View Slide

  62. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    environ = {
    "REQUEST_METHOD": "GET",
    "SCRIPT_NAME": "",
    "PATH_INFO": "/",
    "QUERY_STRING":"search=red+blue&maximum_price=20",
    "SERVER_NAME": "www.example.org",
    "SERVER_PORT": 443,
    "REMOTE_HOST": "134.56.78.4",
    "REMOTE_PORT": 1453,
    "SERVER_PROTOCOL": "HTTP/1.1",
    "HTTP_HOST": "www.example.org",
    "HTTP_ACCEPT": "application/json",
    }

    View Slide

  63. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']

    View Slide

  64. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']

    View Slide

  65. 84(*쎿썗쏚
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ

    View Slide

  66. 84(*쎿썗쏚
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ

    View Slide

  67. 84(*쎿썗쏚
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    •WSGI؀ڥม਺ͷ࡞੒

    View Slide

  68. 84(*쎿썗쏚
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    •WSGI؀ڥม਺ͷ࡞੒
    •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒

    View Slide

  69. 84(*쎿썗쏚
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    •WSGI؀ڥม਺ͷ࡞੒
    •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒
    •WSGIΞϓϦέʔγϣϯͷݺͼग़͠
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']

    View Slide

  70. •WSGI؀ڥม਺ͷ࡞੒
    env = {}
    env['wsgi.version'] = (1, 0) # WSGIͷόʔδϣϯɿܾΊଧͪ
    env['wsgi.url_scheme'] = 'http' # urlͷεΩʔϜ(http/https)
    # HTTP ϦΫΤετຊମͷόΠτྻΛಡΈग़͢͜ͱ͕Ͱ͖ΔೖྗετϦʔϜ
    env['wsgi.input'] = io.BytesIO(byte_request)
    env['wsgi.errors'] = sys.stderr
    env['wsgi.multithread'] = False
    env['wsgi.multiprocess'] = False
    env['wsgi.run_once'] = False
    env['REQUEST_METHOD'] = request_method # GET
    env['PATH_INFO'] = path # /
    env['SERVER_NAME'] = server_name # FQDN
    env['SERVER_PORT'] = str(port) # 8888
    IUUQTXXXQZUIPOPSHEFWQFQTQFQFOWJSPOWBSJBCMFT
    84(*쎿썗쏚

    View Slide

  71. •WSGIΞϓϦέʔγϣϯ͔Βݺͼग़͞ΕΔίʔϧόοΫؔ਺ͷ࡞੒
    IUUQTXXXQZUIPOPSHEFWQFQTQFQUIFTUBSUSFTQPOTFDBMMBCMF
    def start_response(status, response_headers, exc_info=None):
    # ೚ҙͷ಺༰ͷɺWSGIαʔόͰ௥Ճ͢ΔϨεϙϯεϔομ
    server_headers = [
    ('Date', 'Sat, 16 Jul 2016 00:00:00 JST'),
    ('Server', 'HenaWSGIServer 0.1'),
    ]
    global headers_set
    headers_set = [status, response_headers + server_headers]
    84(*쎿썗쏚

    View Slide

  72. 84(*쎿썗쏚
    •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠
    byte_response_body = application(env, start_response)

    View Slide

  73. 84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    def application(environ, start_response):
    start_response(
    '200, OK',
    [('Content-Type', 'text/plain')]
    )
    return [b'Hello, World']
    84(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ

    View Slide

  74. 84(*쎿썗쏚
    •WSGI؀ڥม਺ͱίʔϧόοΫؔ਺ΛҾ਺ͱͨ͠ɺWSGIΞϓϦέʔγϣϯͷݺͼग़͠
    byte_response_body = application(env, start_response)

    View Slide

  75. Server Application
    84(*ॲཧ쎅ྲྀ쎣

    View Slide

  76. Server Application
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  77. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  78. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  79. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺

    View Slide

  80. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME

    View Slide

  81. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME

    View Slide

  82. Server Application
    쎽썗쏵쏚쏍쎹ม਺
    84(*ॲཧ쎅ྲྀ쎣
    84(*؀ڥม਺
    )FMMP 8PSME
    ཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

    View Slide

  83. 84(*쎕썿쎘
    •WSGI͸ɺαʔόͱϑϨʔϜϫʔΫͷڮ౉͠Λ͢Δڞ௨࢓༷
    •WSGI͸ɺཁٻΛड͚औͬͯԠ౴Λฦ͢୯Ұͷಉظݺͼग़͠

    View Slide

  84. 84(*'SBNFXPSL

    View Slide

  85. 84(*4FSWFS
    mod_wsgi

    View Slide

  86. 84(*쎅՝୊
    •asyncio async / await ͷԸܙ
    •WebSocket HTTP/2.0ରԠ

    View Slide

  87. தؒँࣙ
    •ϝϞతͳࢥߟతͳ
    IUUQTUIJOLBNJIBUFOBCMPHDPNFOUSZ
    •ιʔείʔυ
    IUUQTHJUIVCDPNUIJOL"NJTBOECPYXTHJ@XFCTFSWFSTBNQMF
    PythonͰWSGI४ڌͷWebαʔόΛࣗ࡞͠ɺͦͷ্ͰBottleΛಈ͔ͯ͠Έͨ

    View Slide

  88. ͯ͜͜͞Ͱຊηογϣϯͷओ໾
    "4(*

    View Slide

  89. ͢΂ͯ͸BTZODBXBJU͔Β࢝·ͬͨ

    View Slide


  90. IUUQTqPSJNPOEEFWCMPHBSUJDMFTJOUSPEVDUJPOUPBTHJBTZODQZUIPOXFC
    ͢΂ͯ͸BTZODBXBJU͔Β࢝·ͬͨ

    View Slide

  91. 썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶
    •ඇಉظIOͷͨΊͷڞ௨ίϯϙʔωϯτ͕Pythonʹ௥Ճ
    •Pyhton 3.4 ʢ2014೥ʣ ΑΓ asyncio Ϟδϡʔϧ
    •Pyhton 3.5 ʢ2015೥ʣΑΓ async/await ͕ར༻Մೳʹͳͬͨ

    View Slide

  92. 썰쎐썽쎆BTZODBXBJU썢쎠࢝쎕썺썶
    •asyncioɺasync/await ొ৔ޙɺඇಉظͳ Web Framework͕ᷓΕ͍ͯͨ
    •SANICɺTornadoɺaiohttpɺViboraɺJapronto
    Japronto!

    View Slide

  93. ͷɺͰ͠ΐ͏͔

    View Slide

  94. 썴쎙썴쎙쎁쎪쎅썶쎘쎂84(*썣썾썤썶쎅썢
    ϑϨʔϜϫʔΫA WebαʔόA
    WebαʔόB
    WebαʔόC
    WebαʔόD
    ϑϨʔϜϫʔΫB
    ϑϨʔϜϫʔΫC
    ϑϨʔϜϫʔΫD

    View Slide

  95. 썴쎙썴쎙쎁쎪쎅썶쎘쎂"4(*썣썾썤썶쎅썢
    ϑϨʔϜϫʔΫA WebαʔόA
    WebαʔόB
    WebαʔόC
    WebαʔόD
    ϑϨʔϜϫʔΫB
    ϑϨʔϜϫʔΫC
    ϑϨʔϜϫʔΫD
    "4(*

    View Slide

  96. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ

    View Slide

  97. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ
    •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛

    View Slide

  98. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ
    •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛
    •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ

    View Slide

  99. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ
    •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ
    •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛
    •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ

    View Slide

  100. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ
    •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ
    •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛
    •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ
    •·ͩPEPʹ͸ͳ͍ͬͯͳ͍

    View Slide

  101. "4(*쎅ొ৔
    •ASGIʢAsynchronous Server Gateway Interfaceʣͷུ
    •HTTP/1.1ɺWebsocketɺHTTP/2ʹରԠ
    •2016೥ʹRead the Docs͕ొ৔ - 1,2Λܦͯݱࡏ 3 Ͱ ࠷৽൛ͷ҆ఆ൛
    •WSGIͷਫ਼ਆతʢεϐϦνϡΞϧʁʣͳޙܧऀʢa spiritual successorʣ
    •·ͩPEPʹ͸ͳ͍ͬͯͳ͍

    View Slide

  102. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/

    View Slide

  103. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  104. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  105. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  106. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  107. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •coroutine application(scope, receive, send)
    •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  108. "4(*쎂썻썛썽3FBEUIF%PDT
    •WSGIͱޓ׵ͷ͋Δઃܭʹͳ͍ͬͯΔʢasgirefͰWsgiToAsgiͱ͍͏Ξμϓλʔʣ
    https://asgi.readthedocs.io/en/latest/
    •coroutine application(scope, receive, send)
    •ASGIΞϓϦέʔγϣϯ͸ɺ୯Ұͷඇಉظݺͼग़͠Մೳ
    •ASGI ΞϓϦέʔγϣϯ͸ɺasync/await ޓ׵ੑͷ͋ΔίϧʔνϯΛ଴ػ࣮ͯ͠ߦ

    View Slide

  109. "4(*쎂썻썛썽
    •ASGI ͷجຊͷίʔυ͔ΒɺجຊͱͳΔHTTPϦΫΤετͷॲཧΛݟͯΈΔ
    •ASGIΞϓϦέʔγϣϯ
    •ASGIαʔό

    View Slide

  110. "4(*쎂썻썛썽3FBEUIF%PDT
    •ͦͷ΄͔ͷASGIͷ࢓༷
    •ASGI sub-specification - Life Span
    •ASGI Extention - HTTP/2 Server Push
    •ASGI Extention - Websocket Denial Response
    https://asgi.readthedocs.io/en/latest/

    View Slide

  111. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    •ίϧʔνϯ
    •async/await

    View Slide

  112. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。
    •ίϧʔνϯ
    •async/await

    View Slide

  113. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。
    •ίϧʔνϯ
    •async/await

    View Slide

  114. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    •ίϧʔνϯ
    処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること
    コルーチンを定義するには async def を利用します
    •async/await
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。

    View Slide

  115. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    •ίϧʔνϯ
    処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること
    コルーチンを定義するには async def を利用します
    •async/await
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。

    View Slide

  116. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    •ίϧʔνϯ
    •async/await
    async/await構文。asyncでコルーチンを定義し、awaitはコルーチンの
    実行結果を取得するために使用します。
    処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること
    コルーチンを定義するには async def を利用します
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。

    View Slide

  117. "4(*쎂썻썛썽BTZODJPBTZODBXBJU
    •͜ͷޙͷίʔυͰ͸ asyncio async/await͕ొ৔͠·͢ɻ
    •asyncio
    •ίϧʔνϯ
    •async/await
    async/await構文。asyncでコルーチンを定義し、awaitはコルーチンの
    実行結果を取得するために使用します。
    処理を明示的に中断し、再開できるタスクを利用して複数の処理を実行すること
    コルーチンを定義するには async def を利用します
    標準ライブラリに含まれ、コルーチンを活用して主にネットワーク関連の
    IO処理を非同期に行うためのモジュールです。

    View Slide

  118. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    IUUQTXXXVWJDPSOPSH

    View Slide

  119. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    IUUQTXXXVWJDPSOPSH

    View Slide

  120. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    scope

    View Slide

  121. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    = {
    "type": "http",
    "http_version": "2.0",
    "asgi": {
    "spec_version": "2.1",
    "version": “3.0",
    },
    "method": "POST",
    "scheme": "https",
    "path": "/",
    "query_string": b"a=b",
    "headers": [(b"content-length", b"5")],
    "client": ("10.0.0.0", 1234),
    "server": ("127.0.0.1", 443),
    "root_path": ".",
    }
    scope
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMIUUQDPOOFDUJPOTDPQF
    HTTP Connection Scope

    View Slide

  122. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app( , , send):
    assert scope['type'] == 'http'
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    receive
    scope

    View Slide

  123. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    = {
    "type": "http.request.body",
    "body": b'{"example": "Some JSON data"}',
    "more_body": False
    }
    receive
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU
    Request - receive event

    View Slide

  124. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    = {
    "type": "http.request.body",
    "body": b'{"example": "Some JSON data"}',
    "more_body": False
    }
    receive
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU
    Request - receive event

    View Slide

  125. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    = {
    "type": "http.request.body",
    "body": b'{"example": "Some JSON data"}',
    "more_body": False
    }
    receive
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFRVFTUSFDFJWFFWFOU
    Request - receive event

    View Slide

  126. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    receive
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })

    View Slide

  127. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFTQPOTFTUBSUTFOEFWFOU
    Response Start - send event

    View Slide

  128. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMSFTQPOTFTUBSUTFOEFWFOU
    Response Start - send event

    View Slide

  129. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    ‘more_body’:
    })

    View Slide

  130. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    ‘more_body’:
    })
    False

    View Slide

  131. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅ྫ
    async def app(scope, receive, send):
    assert scope[“type”] == “http”
    await send({
    'type': 'http.response.start',
    'status': 200,
    'headers': [
    [b'content-type', b'text/plain'],
    ]
    })
    await send({
    'type': 'http.response.body',
    'body': b'Hello, world!',
    })

    View Slide

  132. "4(*४ڌ쎅쎬쏡쏴쎻썗쏁쏱쏽쎅쎦썢썺썶썪썿
    •Ҿ਺͸3ͭ
    •Scope ɿ ΫϥΠΞϯτ͔ΒͷϦΫΤετͷ৘ใؚ͕·Ε͍ͯΔʢWSGIͷenvironʹ
    ֘౰ʣ
    •recieveɿαʔό͔ΒͷϘσΟͷ৘ใΛड͚औΓͦ͏ͩ
    •sendɿԠ౴։࢝ͷsend ͱ Ԡ౴ຊମͷsend
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMIUUQDPOOFDUJPOTDPQF
    HTTP & WebSocket ASGI Message Format - HTTP

    View Slide

  133. Ͱ͸ଓ͍ͯ
    αʔόଆͷίʔυ

    View Slide

  134. "4(*FDIP8FC쎿썗쏚
    •γϯϓϧͳαʔόͷྫͱͯ͠ɺEuro Python 2020
    IUUQTZPVUVCF(QRY6*8KJX U

    View Slide

  135. •Philip JonesʢPG Jonesʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  136. •Philip JonesʢPG Jonesʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  137. •Philip JonesʢPG Jonesʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  138. •Philip JonesʢPG Jonesʣ
    •ASGI Read the Docs ίϛολʔ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  139. •HTTP1.1ରԠͷASGIαʔόɻߏ੒ͱͯ͠͸େ͖͘ҎԼͷ5ͭɻ
    •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ
    •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    •class HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  140. •HTTP1.1ରԠͷASGIαʔόɻߏ੒ͱͯ͠͸େ͖͘ҎԼͷ5ͭɻ
    •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ
    •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    •class HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  141. •import
    import asyncio
    import sys
    "4(*FDIP8FC쎿썗쏚

    View Slide

  142. •class HTTPParser: HTTPͷϦΫΤετΛύʔε͢Δ
    class HTTPParser:
    def __init__(self):
    self.part = "REQUEST"
    self.headers = []
    self.body_length = 0
    def feed_line(self, line: bytes):
    if self.part == "REQUEST":
    self.method, self.path, self.version = line.split(b" ", 2)
    self.part = "HEADERS"
    elif self.part == "HEADERS" and line.strip() == b"":
    self.part = "BODY"
    elif self.part == "HEADERS":
    name, value = line.split(b":", 1)
    self.headers.append((name.strip(), value.strip()))
    if name.lower() == b"content-length":
    self.body_length = int(value)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  143. def create_scope(parser):
    return {
    "type": "http",
    "method": parser.method,
    "asgi": {
    "spec_version": "2.1",
    "version": "3.0",
    },
    "scheme": "http",
    "raw_path": parser.path,
    "path": parser.path.decode(),
    "headers": parser.headers,
    }
    •create_scope ؔ਺ɿscopeΛ࡞ΔʢASGIΞϓϦͷୈҰҾ਺Λ࡞Δʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  144. def create_message(body, more_body):
    return {
    "type": "http.request",
    "body": body,
    "more_body": more_body,
    }
    •create_message ؔ਺ɿreceive༻ͷϝοηʔδΛ࡞ΔʢASGIΞϓϦͷୈ̎Ҿ਺ʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  145. if __name__ == "__main__":
    if len(sys.argv) < 2:
    sys.exit('"module:callable"ͷܗͰASGIΞϓϦέʔγϣϯΛࢦఆ͍ͯͩ͘͠͞')
    host, port = 'localhost', 8888
    app_path = sys.argv[1]
    module, application = app_path.split(':')
    module = __import__(module)
    asgi_app = getattr(module, application)
    global app
    app = asgi_app
    asyncio.run(main(host, port))
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    "4(*FDIP8FC쎿썗쏚

    View Slide

  146. async def main(host, port):
    server = await asyncio.start_server(asgi_http_parser_server, host, port)
    await server.serve_forever()
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    "4(*FDIP8FC쎿썗쏚

    View Slide

  147. async def main(host, port):
    server = await asyncio.start_server(asgi_http_parser_server, host, port)
    await server.serve_forever()
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    "4(*FDIP8FC쎿썗쏚

    View Slide

  148. async def main(host, port):
    server = await asyncio.start_server(asgi_http_parser_server, host, port)
    await server.serve_forever()
    •mainॲཧɾmainίϧʔνϯɿasyncio Ͱcreateserver
    "4(*FDIP8FC쎿썗쏚

    View Slide

  149. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    •গ͠௕͍ͷͰ̐෼ׂ͠·͢ʢ40ߦ͙Β͍Ͱ͢ʣ
    "4(*FDIP8FC쎿썗쏚

    View Slide

  150. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    async def asgi_http_parser_server(reader, writer):
    parser = HTTPParser()
    receive = asyncio.Queue()
    read = 0
    while not reader.at_eof():
    if parser.part != "BODY":
    parser.feed_line(await reader.readline())
    elif parser.body_length == 0:
    await receive.put(create_message(b"", False))
    break
    else:
    body = await reader.read(100)
    read += len(body)
    await receive.put(create_message(body, read < parser.body_length))
    if read >= parser.body_length:
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  151. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    async def asgi_http_parser_server(reader, writer):
    parser = HTTPParser()
    receive = asyncio.Queue()
    read = 0
    while not reader.at_eof():
    if parser.part != "BODY":
    parser.feed_line(await reader.readline())
    elif parser.body_length == 0:
    await receive.put(create_message(b"", False))
    break
    else:
    body = await reader.read(100)
    read += len(body)
    await receive.put(create_message(body, read < parser.body_length))
    if read >= parser.body_length:
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  152. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    async def asgi_http_parser_server(reader, writer):
    parser = HTTPParser()
    receive = asyncio.Queue()
    read = 0
    while not reader.at_eof():
    if parser.part != "BODY":
    parser.feed_line(await reader.readline())
    elif parser.body_length == 0:
    await receive.put(create_message(b"", False))
    break
    else:
    body = await reader.read(100)
    read += len(body)
    await receive.put(create_message(body, read < parser.body_length))
    if read >= parser.body_length:
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  153. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    # httpͷϦΫΤετͷparser͔ΒscopeΛ࡞Δ
    scope = create_scope(parser)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  154. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    # httpͷϦΫΤετͷparser͔ΒscopeΛ࡞Δ
    scope = create_scope(parser)
    {
    "type": "http",
    "http_version": "2.0",
    "asgi": {
    "spec_version": "2.1",
    "version": “3.0",
    },
    "method": "POST",
    "scheme": "https",
    "path": "/",
    "query_string": b"a=b",
    "headers": [(b"content-length", b"5")],
    "client": ("10.0.0.0", 1234),
    "server": ("127.0.0.1", 443),
    "root_path": ".",
    }
    "4(*FDIP8FC쎿썗쏚

    View Slide

  155. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    send = asyncio.Queue()
    await app(scope, receive.get, send.put)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  156. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    send = asyncio.Queue()
    await app(scope, receive.get, send.put)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  157. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    send = asyncio.Queue()
    await app(scope, receive.get, send.put)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  158. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    send = asyncio.Queue()
    await app(scope, receive.get, send.put)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  159. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    send = asyncio.Queue()
    await app(scope, receive.get, send.put)
    "4(*FDIP8FC쎿썗쏚

    View Slide

  160. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  161. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  162. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message[“type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  163. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message[“type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  164. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message[“type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  165. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  166. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  167. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  168. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    while True:
    message = await send.get()
    if message["type"] == "http.response.start":
    writer.write(b"HTTP/1.1 %d\r\n" % message["status"])
    for header in message["headers"]:
    writer.write(b"%s: %s\r\n" % (header))
    writer.write(b"\r\n")
    elif message["type"] == "http.response.body":
    if message.get("body") is not None:
    writer.write(message["body"])
    writer.write(b"\r\n")
    if not message.get("more_body", False):
    break
    "4(*FDIP8FC쎿썗쏚

    View Slide

  169. •asgi_http_parser_server ίϧʔνϯɿΞϓϦέʔγϣϯͱ΍ΓͱΓͷϝΠϯ
    await writer.drain()
    writer.close()
    "4(*FDIP8FC쎿썗쏚

    View Slide

  170. "4(*FDIP8FC쎿썗쏚쎕썿쎘
    •࢓༷ʹͦͬͨ3ͭͷҾ਺ʢscope,receive,sendʣ
    •async/await ͰΞϓϦέʔγϣϯͱ΍ΓͱΓ
    •ίϧʔνϯͷதʹɺreceiveɺsendͷϧʔϓॲཧ
    •୯Ұͷඇಉظݺͼग़͠

    View Slide

  171. "4(*FDIP8FC쎿썗쏚쎕썿쎘
    •࢓༷ʹͦͬͨ3ͭͷҾ਺ʢscope,receive,sendʣ
    •async/await ͰΞϓϦέʔγϣϯͱ΍ΓͱΓ
    •ίϧʔνϯͷதʹɺreceiveɺsendͷϧʔϓॲཧ
    •୯Ұͷඇಉظݺͼग़͠

    View Slide

  172. "4(*)551쏫쏍쏅썗쏂
    Server Application

    View Slide

  173. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }

    View Slide

  174. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }
    {
    "type": "http.request",
    "body": b'',
    "more_body": False
    }

    View Slide

  175. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }
    {
    "type": "http.request",
    "body": b'',
    "more_body": False
    }
    {
    "type": "http.response.start",
    "status": 200,
    "headers": [(b"name", b"value")],
    }

    View Slide

  176. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }
    {
    "type": "http.request",
    "body": b'',
    "more_body": False
    }
    {
    "type": "http.response.start",
    "status": 200,
    "headers": [(b"name", b"value")],
    }
    {
    "type": "http.response.body",
    "body": b"Hello, World",
    "more_body": False,
    }

    View Slide

  177. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }
    {
    "type": "http.request",
    "body": b'',
    "more_body": False
    }
    {
    "type": "http.response.start",
    "status": 200,
    "headers": [(b"name", b"value")],
    }
    {
    "type": "http.response.body",
    "body": b"Hello, World",
    "more_body": False,
    }

    View Slide

  178. "4(*)551쏫쏍쏅썗쏂
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'http'
    }
    {
    "type": "http.request",
    "body": b'',
    "more_body": False
    }
    {
    "type": "http.response.start",
    "status": 200,
    "headers": [(b"name", b"value")],
    }
    {
    "type": "http.response.body",
    "body": b"Hello, World",
    "more_body": False,
    }
    {"type": "http.disconnect"}

    View Slide

  179. ໰͍

    View Slide

  180. ໰썛
    ඇಉظαʔόͱ͸ʁ
    ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε
    "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

    View Slide

  181. ౴͑

    View Slide

  182. ౴썟
    asyncio Ͱ࡞ͬͨWebαʔό
    ඇಉظαʔόήʔτ΢ΣΠΠϯλʔϑΣʔε
    "TZODISPOPVT4FSWFS(BUFXBZ*OUFSGBDF

    View Slide

  183. "4(*쎂썻썛썽3FBEUIF%PDT
    https://asgi.readthedocs.io/en/latest/
    ASGI applications must run as async / await compatible
    coroutines (i.e. asyncio-compatible)

    View Slide

  184. "4(*쎂썻썛썽3FBEUIF%PDT
    ASGI ΞϓϦέʔγϣϯ͸ async / await ޓ׵ͷίϧʔνϯ (͢ͳ
    Θͪ asyncio ޓ׵) ͱ࣮ͯ͠ߦ͞Εͳ͚Ε͹ͳΓ·ͤΜ ɻ
    https://asgi.readthedocs.io/en/latest/
    ASGI applications must run as async / await compatible
    coroutines (i.e. asyncio-compatible)

    View Slide

  185. "4(*쎂썻썛썽3FBEUIF%PDT
    ASGI ΞϓϦέʔγϣϯ͸ async / await ޓ׵ͷίϧʔνϯ (͢ͳ
    Θͪ asyncio ޓ׵) ͱ࣮ͯ͠ߦ͞Εͳ͚Ε͹ͳΓ·ͤΜ ɻ
    https://asgi.readthedocs.io/en/latest/
    ASGI applications must run as async / await compatible
    coroutines (i.e. asyncio-compatible)

    View Slide

  186. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠

    View Slide

  187. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠
    asyncioରԠͰɺ͋ͷIFʢҾ਺3ͭͷ΍ͭʣ

    View Slide

  188. "4(*ରԠ쎅ʓʓ쎂ग़ձ썺썶쎠
    asyncioରԠͰɺ͋ͷIFʢҾ਺3ͭͷ΍ͭʣ
    ͳΜͩͳͱࢥ͍ͬͯͩ͘͞ɻ

    View Slide

  189. "4(*쎂썻썛썽3FBEUIF%PDT
    •ͦͷ΄͔ͷASGIͷ࢓༷
    •ASGI sub-specification - Life Span
    •ASGI Extention - HTTP/2 Server Push
    •ASGI Extention - Websocket Denial Response
    https://asgi.readthedocs.io/en/latest/

    View Slide

  190. "4(*8FC4PDLFU
    Server Application
    {
    'asgi': {'spec_version': ‘2.1',
    'version': '3.0'},
    ...
    'method': ‘GET',
    'type': 'websocket'
    }
    {
    “type": "websocket.connect"
    }
    {
    “type": “websocket.accept"
    }
    {
    “type": “websocket.close”
    “code": 1000
    }
    {
    “type": “websocket.send”
    “text": ”Hello, World”
    }
    {
    “type": “websocket.disconnect"
    }
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTXXXIUNMXFCTPDLFU

    View Slide

  191. "4(*-JGF4BQBO
    "scope" : {
    "type": "lifespan",
    "asgi": {"spec_version": "2.0", "version": "3.0"},
    }
    --- SERVER
    {"type": "lifespan.startup"}
    {"type": "lifespan.shutdown"}
    --- APPLICATION
    {"type": "lifespan.startup.complete"}
    {"type": "lifespan.shutdown.complete"}

    View Slide

  192. "4(*-JGF4BQBO
    async def app(scope, receive, send):
    if scope['type'] == 'lifespan':
    while True:
    message = await receive()
    if message['type'] == 'lifespan.startup':
    ... # Do some startup here!
    await send({'type': 'lifespan.startup.complete'})
    elif message['type'] == 'lifespan.shutdown':
    ... # Do some shutdown here!
    await send({'type': 'lifespan.shutdown.complete'})
    return
    else:
    pass # Handle other types
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTMJGFTQBOIUNM

    View Slide

  193. "4(*TVCTQFDJpDBUJPO-JGF4BQBO
    async def app(scope, receive, send):
    if scope['type'] == 'lifespan':
    while True:
    message = await receive()
    if message['type'] == 'lifespan.startup':
    ... # Do some startup here!
    await send({'type': 'lifespan.startup.complete'})
    elif message['type'] == 'lifespan.shutdown':
    ... # Do some shutdown here!
    await send({'type': 'lifespan.shutdown.complete'})
    return
    else:
    pass # Handle other types
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUTQFDTMJGFTQBOIUNM

    View Slide

  194. "4(*&YUFOTJPOT)5514FSWFS1VTI
    "scope": {
    ...,
    "extensions": {"http.response.push": {}},
    }
    ---
    {
    "type": "http.response.push",
    "path": "/path",
    "headers": [(b"name", b"value")],
    }
    Server
    Application
    IUUQTBTHJSFBEUIFEPDTJPFOMBUFTUFYUFOTJPOTIUNMIUUQTFSWFSQVTI

    View Slide

  195. "4(*&YUFOTJPOT8FCTPDLFU%FOJBM3FTQPOTF
    "scope": {
    ...
    "extensions": {
    "websocket.http.response": {},
    },
    }

    View Slide

  196. "4(*'SBNFXPSLT

    View Slide

  197. "4(*'SBNFXPSLT$PNQBSFE

    Framework HTTP WebSocket Server Push WebSocket HTTP response
    Quart ✓ ✓ ✓ ✓
    FastAPI ✓ ✓ ❌ ❌
    Responder ✓ ✓ ❌ ❌
    Starlette ✓ ✓ ❌ ❌
    Django ✓ ✓ ❌ ❌

    View Slide

  198. "4(*4FSWFST

    Daphne Mangum

    View Slide

  199. "4(*4FSWFST

    $PNQBSFE

    Framework HTTP WebSockets Server Push WebSocket
    HTTP response
    Hypercorn 1 ✓ 2 ✓ 1 ✓ 2 ✓ ✓ ✓
    Uvicorn 1 ✓ 2 ❌ 1 ✓ 2 ❌ ❌ ❌
    Daphne 1 ✓ 2 ✓ 1 ✓ 2 ❌ ❌ ❌
    Mangum 1 ✓ 2 ❌ 1✓ 2 ❌ ❌ ❌

    View Slide

  200. "4(*쎕썿쎘
    •ASGIରԠ ʹ asyncio
    •ASGIରԠϑϨʔϜϫʔΫ͸૿͍͑ͯΔ
    •ASGIରԠͷαʔό΋͋Δ
    •ASGI͸PEPʹͳ͍ͬͯͳ͍

    View Slide

  201. 84(*썿"4(*쎕썿쎘
    •WSGI ͱ ASGI ͷ໨త͸ಉ͡
    •WSGI ͱ ASGI ͷ࣮૷͸ࣅ͍ͯΔʢͨͩasync/awitͰܾఆతʹҧ͏ʣ
    •WSGI ͱ ASGI ͷঢ়گ΋ࣅ͍ͯΔ
    •ASGI͸PEPʹͳͬͯ΋Α͍ͷͰ͸

    View Slide

  202. "4(*Λ
    औΓר͘ঢ়گ

    View Slide

  203. "4(*1&1쎏쎅ಓ
    ͳͥASGI͸PEPʹͳ͍ͬͯͳ͍ͷ͔ʁ

    View Slide

  204. "4(*1&1쎏쎅ಓ
    ͳͥASGI͸PEPʹͳ͍ͬͯͳ͍ͷ͔ʁ
    A.ίΞσϕϩούʔ͕͍͍إΛ͠ͳ͔͔ͬͨΒ

    View Slide

  205. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔
    [email protected] ϝʔϦϯάϦετ 2018೥10݄28೔

    View Slide

  206. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2018೥10݄28೔
    Standardising ASGI as a PEP
    IUUQTNBJMQZUIPOPSHBSDIJWFTMJTUQZUIPOJEFBT!QZUIPOPSHUISFBE5$#133**#/7%8/+$9**/.$92,3,$3

    View Slide

  207. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔
    Subject:Is the deployment standard for WSGI ready?

    View Slide

  208. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔
    Subject:Is the deployment standard for WSGI ready?

    View Slide

  209. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔
    Subject:Is the deployment standard for WSGI ready?
    *EPOUUIJOLUIJTTPSUPGUIJOHTIPVMECFB1&1
    -PPLBU"4(*BOEIPXUIBUJTOUB1&1BOETUJMMNBOBHFTUPFYJTU
    4JODFUIJTJTO`UBMBOHVBHFSFMBUFEPSQBDLBHFSFMBUFEUIJOH*EPOUUIJOLJUSFBMMZOFFETUPHPUISPVHIUIF1&1
    QSPDFTT

    View Slide

  210. "4(*1&1쎏쎅ಓ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔
    Subject:Is the deployment standard for WSGI ready?
    *EPOUUIJOLUIJTTPSUPGUIJOHTIPVMECFB1&1
    -PPLBU"4(*BOEIPXUIBUJTOUB1&1BOETUJMMNBOBHFTUPFYJTU
    4JODFUIJTJTO`UBMBOHVBHFSFMBUFEPSQBDLBHFSFMBUFEUIJOH*EPOUUIJOLJUSFBMMZOFFETUPHPUISPVHIUIF1&1
    QSPDFTT
    4JODF84(*BOE QSPCBCMZTPPO
    "4(*BSFWFSZDPNNPO"1*TUBOEBSETJO1ZUIPOMBOE UIFZEFTFSWFUP
    HPJOUPUIF1&1JOEFYBTXFMM *.0

    View Slide

  211. "4(*1&1쎏쎅ಓ
    It's worth noting that I was discouraged from making ASGI a PEP by
    several Python core developers, which is why I have not been
    pursuing that process any further. I'm not sure I share this view,
    so I may come back to it in the future, but there's a reason it's
    not in the process right now.
    ಛච͢΂͖͸ɺࢲ͕ASGIΛPEPʹ͢Δ͜ͱΛԿਓ͔ͷPythonίΞ։ൃऀ͔Βམ୾͞Εͯ
    ͍ͨ͜ͱͰɺͦΕҎ্ͦͷϓϩηεΛ௥ٻͯ͜͠ͳ͔ͬͨ͜ͱͰ͢ɻ
    ࢲ͸͜ͷݟղʹڞײ͍ͯ͠ΔΘ͚Ͱ͸ͳ͍ͷͰɺকདྷతʹ͸໭ͬͯ͘Δ͔΋͠Ε·ͤΜ
    ͕ɺࠓ͸ͦͷϓϩηεʹೖ͍ͬͯͳ͍ͷʹ͸ཧ༝͕͋Γ·͢ɻ
    [email protected] ϝʔϦϯάϦετ 2020೥1݄28೔

    View Slide

  212. •Awesome ASGI ͱ͍͏GithubϦϙδτϦ
    “࠷΋༏ΕͨASGIϓϩδΣΫτͱϦιʔεΛ࠷৽ͷঢ়ଶʹอͭͷʹ໾ཱͪ·͢“
    "4(*쎅੝쎡্썣쎡
    IUUQTHJUIVCDPNqPSJNPOENBODBBXFTPNFBTHJ

    View Slide

  213. "4(*쎅੝쎡্썣쎡
    •Awesome ASGI ͱ͍͏GithubϦϙδτϦ
    •Web Framework
    •Server
    •Monitoring
    •ServerlessʢAWSʣ
    •GraphQL

    View Slide

  214. •Encode OSS ͱ͍͏ΠΪϦεͷձࣾ
    "4(*쎅੝쎡্썣쎡
    IUUQTXXXFODPEFJP

    View Slide

  215. •Encode OSS ͱ͍͏ΠΪϦεͷձࣾ - ༷ʑͳϓϩμΫτͷ։ൃݩ
    •uvicorn
    •starletteʢFastAPI΍Responder ͷϕʔεʹͳ͍ͬͯΔ࠷খASGI FWʣ
    •HTTPX
    •Django REST framework
    •ASGIهࣄ΋͋Γ - Hello, ASGI ͳͲͳͲ
    "4(*쎅੝쎡্썣쎡

    View Slide

  216. •PG Jones ࢯ
    •ASGI ׬શରԠͷαʔό Hypercorn / ϑϨʔϜϫʔΫͷQuart
    •༷ʑͳͱ͜ΖͰͷਫ਼ྗతͳొஃ
    "4(*쎅੝쎡্썣쎡
    IUUQTQHKPOFTEFW

    View Slide

  217. ଎౓쎅࿩
    IUUQTXXXUFDIFNQPXFSDPNCFODINBSLT

    View Slide

  218. 1&1쎏쎅ಓ
    •ASGI͸·ͩ࢝·ͬͨ͹͔Γ
    •PythonʹࠓؔΘ͍ͬͯΔΘ͕ͨͨͪ͠ҭ͍͚ͯͯΔ΋ͷ
    •·ͣ͸͞ΘͬͯΈ͍ͯͩ͘͞
    •ͻͱ·ͣࢼ͢ͷͰ͋Ε͹ɺFastAPIͱuvicornͰɻ
    •αʔόʔϓογϡ΍HTTP/2Λࢼ͚ͨ͠Ε͹ɺQuartͱHypercornΛɻ

    View Slide

  219. ࢀߟࢿྉ
    •An ASGI Server from scratch / Philip Jones
    IUUQTXXXZPVUVCFDPNXBUDI W(QRY6*8KJX
    •An introduction to ASGI, Asynchronous Server Gateway Interface / Philip Jones
    IUUQTXXXZPVUVCFDPNXBUDI WUH$,2R986
    •Hello, ASGI
    IUUQTXXXFODPEFJPBSUJDMFTIFMMPBTHJ
    •Introduction to ASGI: Emergence of an Async Python Web Ecosystem
    IUUQTqPSJNPOEEFWCMPHBSUJDMFTJOUSPEVDUJPOUPBTHJBTZODQZUIPOXFC

    View Slide