当前行为(F151,2026-10-15):用户反馈v1兼容替换重启后仍memory_status_unavailable,要求去除应用内存管理。Admission.acquire()现只检查共享任务名额,不读取RSS、MemAvailable或cgroup,也不按内存预算/任务预留拒绝;因此正常接纳不再产生memory_status_unavailable或memory_busy。问答、公司分类和后台扫描/分析均复用这一实现。共享名额API_MEMORY_MAX_JOBS、接口/模型/检索并发、同会话互斥及断线持有名额规则保持;满额仍返回429 server_busy。旧内存预算配置保留兼容解析与校验,但不参与运行时接纳,无需修改.env。
运行时只需替换src/step4_api/memory.py,按原部署入口重启后重试原curl;先前的独立read_memory()诊断仍可能报错,但已不参与请求接纳,不作为重启前提。Linux systemd硬隔离与附件解析子进程限额独立保留,不在本轮卸载;未安装unit时不会新增系统级限额。应用不再根据剩余内存预先拒绝工作,资源耗尽仍可能由系统终止进程。尚未执行148现场替换或真实问答验证。
以下应用采样和预算内容为F104/F150历史机制,已由F151取代;保留以便解释诊断函数和旧版本。Linux硬隔离必须在服务器安装并启用生成的systemd unit后才生效,仍按下方要求使用。
问答、公司分类、DMS后台扫描和后台分析共享一个Admission。锁内读取RSS及系统可用内存;Linux同时取可见cgroup内存控制器各级剩余内存的最小值,Windows读取系统内存和进程工作集。读数失败保守拒绝。Windows没有本轮新增的服务级硬限制。
F150(2026-10-15):应用内存采样兼容cgroup v1和v2。根据/proc/self/cgroup选择实际memory控制器,混合模式下memory归v1时优先读v1;v1按/proc/self/mountinfo定位挂载点及根,读取memory.limit_in_bytes和memory.usage_in_bytes,检查当前组和可见祖先,处理无限额、合并控制器、路径转义及命名空间。没有有限额时仍检查系统MemAvailable、进程RSS与任务预算;内存不足返回429,挂载/字段缺失、权限或解析失败仍返回503,不退化为忽略cgroup限制。此兼容只改变应用采样,下方生成的systemd硬隔离仍要求v2;v1不宣称支持该unit的硬隔离。
148现场已在项目目录复现旧版OSError: cgroup_v2_required;当前终端的N:memory:/路径确认v1 memory控制器,不能由此假定独立容器或其他命名空间中的所有进程均相同。替换src/step4_api/memory.py后,在项目根目录用部署解释器只读验证:
"$(cat output/deploy/python-path)" -c 'from src.step4_api.memory import read_memory; print(read_memory())'
在F150版本中预期输出Memory(rss=..., available=...)而非traceback;诊断进程的RSS不是API进程RSS。用户反馈现场重启后仍503,第二次采样失败原因未确认。F151不再调用此诊断函数接纳工作,现场重启后应直接验证POST /api/chat的回答或error,不再要求先通过采样。
| 配置 | 默认 | 说明 |
|---|---|---|
| API_MEMORY_MAX_JOBS | 4 | 共享重任务上限,范围2–32;扫描占1个,每个新分析另占1个 |
| API_MEMORY_BUDGET_MB | 4096 | RSS加任务预留的接纳预算,正整数,必须大于单任务预留 |
| API_MEMORY_JOB_RESERVE_MB | 256 | 每个活动及待接纳任务的额外增长预留,正整数,不是实测占用或硬限额 |
| API_MEMORY_MIN_AVAILABLE_MB | 512 | 系统/cgroup额外可用内存底线,正整数 |
同名系统环境变量优先于.env。上表为代码默认值。F106按用户要求将本地.env调整为共享名额8、接纳预算8192MiB、系统余量1024MiB,每任务预留256MiB保持,需重启生效。满8个任务合计额外预留2048MiB,仍须满足RSS与可用内存检查,不能保证始终接满8个。模型/检索并发未扩大,未实测服务器容量。生产unit将应用预算设为硬预算的75%,覆盖.env同名值。
接纳条件:活动数未达上限;RSS + (活动数 + 1) × 预留 ≤ 应用预算;可用内存 ≥ 底线 + (活动数 + 1) × 预留。预留与已增长RSS叠加是有意保守计算。4个名额不等于4个用户;原会话互斥、API接纳、模型/检索限流继续生效。
问答/分类返回429 memory_busy或server_busy;采样失败返回503 memory_status_unavailable,均带Retry-After: 2。前端提示服务繁忙、稍后重试,不能显示为无政策结果,也不要无限立即重试。后台容量不足延后,不扫描、不消耗模型尝试次数;扫描中无分析名额则保留待分析状态。任务完成/失败释放名额,断线/HTTP超时不提前释放仍运行的任务。容量恢复后下次请求/扫描重新判断。
接纳保护不强行取消在途调用、不主动回收本地库内存;未新增知识原文/Redis检查点字节硬上限。启动BGE加载早于请求接纳,须由硬隔离覆盖。4GB应用预算不是实际峰值保证。
保留单附件10MiB、每轮下载32MiB及已有解压/文本/页数边界。Linux解析子进程读输入前设置1.5GiB RLIMIT_AS(虚拟地址空间),已有更小硬限制不放宽;不使用多线程API中的preexec_fn。子进程BLAS/OMP线程设1,主API配置不变。复杂文件可能被拒绝;MemoryError返回document_memory_limit,库包装的异常或子进程被杀可能仍为document_parse_failed,不伪装成功。
要求标准/sys/fs/cgroup挂载的cgroup v2内存控制器、支持MemoryMax/MemorySwapMax/OOMPolicy的systemd(建议244及以上),及原部署要求。生成器只写工作区文件,不安装或启动服务。v1/非标准挂载须先调整部署,不要关闭检查冒充隔离已生效。
服务器准备好依赖/知识后,由有systemd管理权限的运维执行。4096MiB仅为示例,应按整机内存减去Redis/Milvus等其他服务与系统余量后分配,不能把整机内存全给API。assistant替换为已有非root用户,须能读取项目/模型/配置/环境并写入所需目录。
SERVICE_PYTHON=$(cat output/deploy/python-path)
UNIT_PATH=$("$SERVICE_PYTHON" scripts/memory_service.py --user assistant --memory-max-mb 4096)
UNIT_NAME=$(basename "$UNIT_PATH")
sudo systemd-analyze verify "$UNIT_PATH"
# 首次切换先停旧进程,再安装unit,避免重叠。
sh deploy.sh stop
sudo install -m 0644 "$UNIT_PATH" "/etc/systemd/system/$UNIT_NAME"
sudo systemctl daemon-reload
sudo systemctl enable --now "$UNIT_NAME"
sudo systemctl show "$UNIT_NAME" -p MainPID -p MemoryCurrent -p MemoryHigh -p MemoryMax -p MemorySwapMax -p ControlGroup
sudo systemctl status "$UNIT_NAME"
MemoryHigh=硬预算87.5%、MemoryMax=硬预算、MemorySwapMax=0,预算覆盖API及解析子进程。OOMPolicy=kill、KillMode=control-group使内存故障/停止针对服务组;异常退出10秒后重启,5分钟最多3次启动,避免重启风暴。触及硬限额可能终止正在进行的问答。系统或其他服务内存耗尽仍可能影响本服务。
生产入口要求读到不高于指定硬预算的有限cgroup限制,否则启动失败。API_REQUIRE_MEMORY_CGROUP和API_MEMORY_HARD_LIMIT_MB由生成器设置用于检查,不要删除。生成unit名含项目路径指纹;ExecStart通过deploy.sh serve前台启动,每次读取output/deploy/python-path,因此更新依赖后不绑定旧环境。
安装后原deploy/start/stop/restart入口转由systemctl管理该unit,权限失败不会回退为无限额后台进程,执行者需有相应权限。启动就绪核对systemd MainPID与本项目API身份。不要并行手工启动python -m src.step4_api绕过隔离,不要移动已安装unit对应的项目。systemd日志用journalctl -u查看,原后台模式仍用output/deploy/api.log。
采样字段及层级依据:Linux cgroup v1内存控制器、Linux cgroup v2。v1的usage为内核近似计数,应用预留不构成容量保证;只读取当前命名空间可见的祖先,未实测生产负载或隐藏祖先的余量。
合成测试覆盖并发不超售、内存/可用量拒绝、采样失败、恢复、提交/工作失败释放、断线持有、前后台共享、延后不耗尝试次数;模拟cgroup祖先及命名空间、缺失硬限制拒绝启动、检查unit参数与部署无回退。未耗尽真实内存、未真实模型/DMS测试,未在Linux验证unit及解析器硬限制。
Redis、Milvus、知识更新/入库是独立服务或命令,不受API unit覆盖。同机须分别分配资源限额;Redis还应按会话恢复语义选择maxmemory策略,不任意淘汰会话。本轮未修改这些服务。生产容量、持续运行内存趋势、GPU显存、真实Linux附件兼容性待验证,不能宣称整台服务器绝不会OOM。