如何触发 FastAPI/Uvicorn 的干净关闭

jkf*_*ers 5 python windows subprocess fastapi uvicorn

我正在使用 uvicorn 和 python 的 subprocess.Popen 运行多个 FastAPI 实例。我有一个用 PySimpleGUI 制作的小型 GUI,我希望能够随意关闭服务器并重新启动它们。

我遇到的第一个问题是,至少在 Windows 中,启动 uvicorn 服务器似乎创建的不是一个,而是两个新进程,并且调用Popen.terminate()仅关闭其中一个进程,这不会释放与服务器关联的端口。我使用 psutil 包修复了此问题,以检查实例化 Popen 对象后创建了哪些新进程,并使用 psutil 跟踪和终止第二个进程。

还有一个主要问题是,调用psutil.terminate()进程并没有调用.net下的FastAPI函数@app.on_event("shutdown")。过去,我们在单独的终端窗口中运行所有服务器,并发现这些终端窗口上的 ctrl-c 将调用关闭事件,但我没有找到其他方法来执行此操作。我界面上的 ctrl-c 显然会关闭界面和所有服务器,并且在命中所有服务器的关闭事件方面有些不可靠。我的另一个想法是 use psutil.send_signal(signal.CTRL_C_EVENT),但这与在终端中调用 ctrl-c 具有相同的效果。

所以我很茫然。我看到很多帖子说这是 uvicorn 的普遍缺点,但没有看到任何直接证实我自己的经验或提供解决方案的内容。我还知道 FastAPI 中的“关闭”和“启动”事件是从 Starlette 移植的,并且在这两个包中都没有很好的记录。我看到过使用 guvicorn 的建议,但我的简短调查证实它与 Windows 不兼容。有什么建议么?

小智 -2

长话短说:

  • API 是长期运行的进程
  • 整个行业都围绕虚拟化来自动管理何时启动或停止服务的编排
  • 还有“无服务器”基础设施,您可以挂起任何流程,而无需在该领域花费任何精力,因为它本来就不是一件事
  • 如果您仍然想与其他人对抗并自己管理它,您可以按照这个回答的问题进行操作
    ##### SOLUTION #####
    pid = proc.pid
    parent = psutil.Process(pid)
    for child in parent.children(recursive=True):
        child.kill()
    ##### SOLUTION END ####
Run Code Online (Sandbox Code Playgroud)

一点解释:

从 Rest API 作为一种架构模式的概念来看,它意味着始终等待来自网络的用户请求。优雅地管理和开发产品来优雅地处理“本来应该永远运行”的事物的关闭从来都不是普遍的意图,我们构建流程来努力保持其作为一个行业 24/7/365 的运行。

如果您想利用在同一设备上同时启动或停止一对多 API 的能力,强烈建议您至少使用容器和 Kubernetes 之类的东西,并且只需针对 Kubernetes CLI 编写命令脚本即可实现此目的。作为额外努力的回报,您将获得与其他人和基本操作系统层的进程隔离(这仍然比您自己构建所有工具要省力。我个人最喜欢的是甚至不这样做,而是直接使用 lambdas在很多方面都变得更容易、更好。不要从我那里得到它,而是从行业领先的公司之一 Cloudflare 及其关于该主题的声明那里得到的

与传统的基于云或以服务器为中心的基础设施相比,无服务器计算具有许多优势。对于许多开发人员来说,无服务器架构提供了更大的可扩展性、更大的灵活性和更快的发布时间,而且成本更低。