如何在FastAPI无客户端请求达指定时长后关闭AWS EC2 Windows实例
实现方案
以下是两种适配你场景的可落地方案:
方案1:FastAPI中间件+本地定时任务实现(无额外服务依赖,判断精度最高)
无需调用AWS接口,全部逻辑在EC2实例本地完成,完全匹配FastAPI请求的空闲判断需求:
- 第一步:给FastAPI添加全局中间件,记录每次请求的最后时间戳,代码示例如下:
from fastapi import FastAPI, Request import time app = FastAPI() # 初始化最后请求时间为服务启动时间 LAST_REQUEST_TIME = time.time() # 全局中间件,每次收到客户端请求就更新时间 @app.middleware("http") async def record_request_time(request: Request, call_next): global LAST_REQUEST_TIME LAST_REQUEST_TIME = time.time() response = await call_next(request) return response # 新增内部巡检接口,供本地定时任务查询空闲时长 @app.get("/_internal/check_idle") def check_idle_status(): idle_minutes = (time.time() - LAST_REQUEST_TIME) / 60 return {"idle_minutes": idle_minutes, "over_30min": idle_minutes > 30}
- 第二步:编写本地巡检Python脚本,判断满足空闲条件时执行Windows关机:
import requests import os if __name__ == "__main__": try: # 端口替换为你实际的uvicorn监听端口 resp = requests.get("http://127.0.0.1:8000/_internal/check_idle", timeout=3) if resp.json().get("over_30min"): # 执行Windows关机命令:/t 60表示60秒后关机,可自行调整时间 os.system('shutdown /s /t 60 /c "FastAPI服务空闲超过30分钟,自动关机"') except: # 若FastAPI服务异常,可根据自身需求决定是否关机,此处默认跳过 pass
- 第三步:配置Windows定时任务触发巡检:打开任务计划程序,新建定时任务,触发器设置为「每5分钟执行一次」,操作设置为启动Python解释器,参数填写巡检脚本的绝对路径即可。
方案2:AWS原生服务实现(无需修改FastAPI代码)
适合不想改动业务代码的场景,依赖CloudWatch指标判断实例空闲状态:
- 前提:给EC2实例绑定具备EC2停止权限的IAM角色
- 操作步骤:进入CloudWatch控制台,给对应EC2实例创建告警,监控
NetworkIn(入站网络流量)指标,规则设置为「连续6个5分钟周期的入站流量低于100KB」(阈值可根据实际系统后台流量大小调整),告警触发动作选择「停止EC2实例」即可。
该方案缺点是会将系统后台产生的入站流量计入统计,空闲判断精度略低于方案1。
注意事项
- 如果你使用uvicorn多进程模式部署FastAPI,不要用全局变量存储最后请求时间,改为存入本地文件或本地Redis,避免多进程数据不同步。
- 测试阶段可以先把关机命令替换为写本地日志的逻辑,确认规则无误后再换成实际关机命令,避免误关实例。
内容的提问来源于stack exchange,提问作者neurocker
相关产品推荐
相关产品推荐

