fd-audit 是 OpenAlgo 项目中用于审计资源泄漏的技能:检查某次变更是否引入文件描述符(FD)泄漏或无界内存增长。OpenAlgo 生产环境以单个长驻 Gunicorn worker 运行(--worker-class eventlet -w 1),部署之间不重启,因此每请求泄漏一次都会累积,最终导致 "Too many open files"、数据库连接被拒、WebSocket 客户端掉线、RSS 上升、OOM 或延迟爬升。使用方式:审计刚做的改动而非整个仓库。先做范围判断,若变更不涉及持描述符对象(SQLAlchemy 引擎/会话、DuckDB 连接、HTTP 客户端、WebSocket、ZeroMQ socket、子进程、文件、原始 socket、线程与执行器、inotify/selectors)或持内存对象(模块级 dict/list/set、缓存、事件总线订阅、SocketIO room、以 symbol/user/strategy 为键的注册表、驻留 DataFrame、捕获大对象的闭包),审计即可结束。随后按约定检查:SQLite 引擎只能经 database.engine_factory.create_db_engine()(应用 NullPool),不得直接 create_engine() 或使用 StaticPool;DuckDB 独立于 engine_factory,需用上下文管理器或保证 .close();每个 scoped_session 须注册到 app.py 的 teardown_appcontext 或使用 with db_session() as session:;HTTP 使用共享 utils/httpx_client.get_httpx_client() 并显式传 timeout=;WebSocket 适配器重连前先关闭旧连接;ZeroMQ 在 shutdown 与适配器 teardown 时关闭,禁用每次调用新建 context;子进程写日志文件而非 PIPE 并 .wait() 回收;线程与执行器用模块级单例;文件用 with。内存方面,每个缓存都要有界,使用 cachetools.TTLCache(maxsize=..., ttl=...);注册表必须有对应移除逻辑,且错误路径也要执行;须检查退出路径(成功、异常/ finally、重连重试循环),其中重试分支的 continue 跳过 close 最常见。疑似泄漏时应实测:用 lsof -p "$PID" | wc -l 或 Linux 下 ls /proc/$PID/fd | wc -l 采样 FD 数,ps -o rss=,vsz= -p "$PID" 看 RSS,并用 tracemalloc 比对快照定位分配点。发现泄漏时不得静默修复或继续其他工作,需报告获取资源的文件与行、未释放的退出路径、属于 FD 还是内存及增长边界,并说明生产成本,随后在应用修复前请求用户批准。
fd-audit
部署与运维
更新于 10-16 00:06