Python异步服务器即使在程序终止后仍保持运行



在我们的代码中,我们创建了一个使用aiohttp-web捕获webhook的应用程序。Application((通过循环.create_server((方法与服务器连接。

有时(读取-很难再现,但经常足够(,即使在代码终止后,侦听服务器也会继续运行。

例如:

> sudo lsof -i -P -n | grep LISTEN
systemd-r  463 systemd-resolve   13u  IPv4   2459      0t0  TCP 127.0.0.53:53 (LISTEN)
sshd       689            root    3u  IPv4  22779      0t0  TCP *:22 (LISTEN)
sshd       689            root    4u  IPv6  22781      0t0  TCP *:22 (LISTEN)
python3   2728          ubuntu    7u  IPv4 334240      0t0  TCP *:8991 (LISTEN)
...
python3   2808          ubuntu    7u  IPv4 351159      0t0  TCP *:8991 (LISTEN)

这导致了当幽灵服务器(或在某些糟糕的情况下的服务器(吃掉了为生者准备的请求时会造成混乱:(

我们运行纯异步-没有线程-没有多处理。有人知道这是怎么发生的,以及如何防止这种情况发生吗我是否可以使用某种上下文管理器或方法,在程序完成后杀死Web服务器

编辑:

  • 当程序到达代码末尾并正常退出时(正在调用shutdown(,就会发生这种情况

裸代码示例。。。

import asyncio
from aiohttp import web
WEBHOOK = "/listen"
class WebServer():
def __init__(self):
self.app = web.Application()
self.app.router.add_post(WEBHOOK, self.webhook_streams)
self.server = None
async def start(self, local_ip, local_port):
if self.server:
return
loop = asyncio.get_event_loop()
self.server = await loop.create_server(
self.app.make_handler(),
local_ip,
local_port,
reuse_port=True, # This will allow to bind to already used port, otherwise it will simply fail if there is ghost server present
)
async def webhook_streams(self, raw):
pass
async def shutdown(self):
print("Shutting down..")
asyncio.get_event_loop().stop()
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
if __name__ == '__main__':
ws = WebServer()
await ws.start("0.0.0.0", 8000)
# ....some other stuff....
await shutdown()

关键是要等到服务器正确关闭所有连接。。。例如,这需要添加到Web服务器类中

async def stop(self):
"stops server"
if not self.server:
return True
self.server.close() # this must be synchronous which is confusing
await self.server.wait_closed() # here you actually wait for server to close
"stopped server...."
return not self.server.is_serving()

最新更新