IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    FastAPI/Starlette 长连接感知断开

    est发表于 2024-01-18 14:44:12
    love 0

    之前写过如何 在服务器重启的时候感知长连接,最近发现折腾复杂了。

    https://github.com/encode/starlette/discussions/1776

    测试代码:

    import asyncio
    
    async def async_streamer():
        try:
            while True:
                yield b"--boundary\r\nContent-Type: text/plain\r\nContent-Length: 1\r\n\r\n1\r\n"
                await asyncio.sleep(0)
        except asyncio.CancelledError:
            print("caught cancelled error")
    
    app = Starlette(routes=[
        Route('/async', async_endpoint),
    ])
    

    跑起来: uvicorn stream:app

    这段代码粗一看没啥大不了的,但是神奇的地方在于,如果去掉 try ... except asyncio.CancelledError ,代码也能正常跑

    
    async def async_streamer():
        while True:
            yield b"--boundary\r\nContent-Type: text/plain\r\nContent-Length: 1\r\n\r\n1\r\n"
            await asyncio.sleep(0)
    

    而且不会报错!最蛋痛的是,这玩意因为是个 while True,如果你里面有打开的数据库连接,是不会中断的,也不会回收的。因为这个 coroutine 没有继续 async for 来消费,就一直挂在进程里当僵尸了!

    加上 try ... except asyncio.CancelledError,能捕获出错,也能处理善后了。

    真是神奇啊。不知道是 uvicorn 的特性,还是 ASGI 都这样。



沪ICP备19023445号-2号
友情链接