适合加@lru_cache的依赖是无状态、参数固定、初始化开销大的函数,如get_settings()、get_jwt_decoder()、get_logger();不适合的包括get_db()、get_current_user()等依赖请求上下文的函数。

直接用 @lru_cache 装饰依赖函数,但必须确保参数可哈希、缓存粒度匹配请求生命周期——否则反而引入竞态或内存泄漏。
哪些依赖适合加 @lru_cache?
只对「无状态、参数固定、初始化开销大」的依赖生效。典型场景包括:
-
get_settings():读取配置文件或环境变量后构造Settings实例,参数通常只有env字符串 -
get_jwt_decoder():加载公钥或解析 JWT 签名算法,不依赖请求上下文 -
get_logger():按模块名返回预配置的logging.Logger实例
不适合缓存的有:get_db()(每个请求需独立连接)、get_current_user()(依赖 Authorization header)、任何含 Request 或 State 参数的依赖。
@lru_cache 的参数怎么设才安全?
关键不是 maxsize 多大,而是缓存键是否唯一且稳定:
- 必须所有参数都是不可变类型(
str、int、tuple),不能传dict或list - 避免用
maxsize=None,尤其在长时运行服务中——缓存会无限增长,最终 OOM - 推荐显式设
maxsize=128或更小,配合typed=True区分int(1)和float(1.0)
错误示例:@lru_cache() def get_db_config(config_dict: dict): ... —— dict 不可哈希,会直接抛 TypeError。
为什么有时缓存没生效?
FastAPI 默认已在请求内复用同一依赖实例,所以 @lru_cache 主要解决的是「跨请求」重复初始化问题。常见失效原因:
- 依赖函数被定义在路由文件里,每次重载模块时函数对象 ID 变化,缓存键失效
- 用了
Depends嵌套调用,外层依赖未缓存,导致内层即使缓存也反复触发 - 参数中混入了
datetime.now()这类动态值,每次调用缓存键都不同
验证方式:在依赖函数开头加 print(f"init at {id(get_settings)}"),观察是否仅首次打印。
真正难处理的是那些「看似可缓存、实则带隐式状态」的依赖,比如封装了连接池但没暴露关闭逻辑的客户端——缓存它等于把连接池锁死在某个线程/协程里。这种必须靠手动单例或全局变量控制,而不是依赖 @lru_cache。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











