llama-swap 模型 TTL 自动卸载完全指南:globalTTL、unloadTimeout 与 cmdStop 实战

📅 发布时间:2026/10/12 1:41:58
llama-swap 模型 TTL 自动卸载完全指南:globalTTL、unloadTimeout 与 cmdStop 实战
后端API网关LLM 网关人工智能大模型本地部署【免费下载链接】llama-swapReliable model swapping for any local OpenAI/Anthropic compatible server - llama.cpp, vllm, etc项目地址https://gitcode.com/gh_mirrors/ll/llama-swap点击查看免费下载llama-swap 默认会让一个模型一直驻留在显存中直到其他模型抢占 GPU 资源才会将其换出。本指南讲解如何用 TTLTime To Live机制按空闲时长自动卸载模型、释放 VRAM涵盖globalTTL、models.*.ttl、unloadTimeout与 Docker 场景下的cmdStop四个配置项的完整配合方式并介绍通过 HTTP 接口与 Web UI 手动按需卸载的操作方法。读完你可以根据自身显存规模与模型加载成本为每个模型设计出合理的自动卸载策略。TTL 解决什么问题默认行为下llama-swap 会一直保持模型处于加载状态直到有新的模型请求需要 GPU 资源时路由才会把旧模型换出swap为新模型。这在单模型场景下没有问题但当你同时让多个模型常驻例如配合分组路由、矩阵路由使用时安静下来的模型就会白白占据宝贵的显存。TTL 机制改变了这一默认行为它让模型在持续空闲一段时间后自动卸载主动把显存还给系统。这样既不需要等到下一次换出才回收资源也不会因为长期不活动而浪费显存。其实现位于 internal/process/process_command.go每当进程进入 Ready就绪状态就会重置一次最近使用时间lastUse一个每秒触发一次的 TTL goroutine 持续检查当模型仍处于 Ready 状态、当前无 in-flight 请求p.inflight.Load() ! 0时跳过、且距上次使用超过 TTL 时长就触发一次卸载并记录日志Unloading model, TTL of %ds reached。注意一个关键点TTL 计时衡量的是不活动时长而非存活时长每一次请求到达都会刷新计时窗口因此持续有流量的模型永远不会被自动卸载。两个核心配置ttl 与 globalTTL配置文件顶层设置全局默认值模型级可以覆盖# global default, in seconds. 0 never unload automatically globalTTL: 0 models: qwen-coder: ttl: 300 # unload after 5 minutes idle cmd: llama-server --port ${PORT} -m /models/qwen.ggufmodels.*.ttl取值的含义valuebehaviour-1默认值继承globalTTL0永不自动卸载 0空闲超过该秒数后自动卸载因此globalTTL: 600而模型不写ttl时所有模型都会在空闲 10 分钟后被卸载想让某个模型保持常驻给它单独设ttl: 0即可退出自动卸载。这一继承关系在配置解析阶段被明确实现见 internal/config/load.go模型默认ttl -1常量MODEL_CONFIG_DEFAULT_TTL定义于 internal/config/model_config.go解析时若发现仍为-1就改写为config.GlobalTTLglobalTTL本身默认值为 0见 internal/config/config.go并且校验规则是globalTTL 0设置为负数会直接报错globalTTL must be 0见 internal/config/load.go模型级ttl 0同样会被拒绝model %s: invalid TTL value %d。这些默认值与覆盖规则都有对应测试佐证例如 internal/config/config_test.go 中的TestConfig_GlobalTTL覆盖了globalTTL作为默认值、模型ttl: 0覆盖全局值、显式ttl覆盖全局值、默认 0 以及负数被拒绝五种情形。配置合并多配置文件场景时globalTTL属于全局冲突检测项两份配置给出不同值会触发conflict at globalTTL错误见 internal/config/merge_test.go。另外globalTTL支持宏展开例如globalTTL: ${GLOBAL_TTL}这类用法由宏机制处理见 internal/config/macros_refactor_test.go。unloadTimeout控制卸载的等待时长而不是卸载时机ttl决定什么时候开始卸载unloadTimeout决定一旦开始卸载最多等待进程多久退出。两者是正交的两件事不要混为一谈。unloadTimeout: 10 # global default, seconds models: docker-llama: unloadTimeout: 30 # docker stop is slow它作用于每一次卸载——包括 TTL 到期自动卸载、手动按需卸载以及路由换出swap时的停旧进程操作。模型级unloadTimeout为 0 时使用全局值。配置层面的继承规则见 internal/config/load.go 与 internal/config/load.go全局unloadTimeout默认值为常量DEFAULT_UNLOAD_TIMEOUT 10秒定义于 internal/config/config.go全局值同样要求 0负数报错unloadTimeout must be 0模型级unloadTimeout 0会被改写为全局默认值因此你在最终生效配置里总能拿到一个非零的明确超时。从源码看卸载超时的取值链路是路由层通过unloadTimeout(modelID)读取配置见 internal/router/base.go把超时传递给进程层进程层在Stop(timeout)中执行killProcess——先发优雅停止信号并等待gracefulTimeout超时未退出则对整个进程组 SIGKILL 强杀见 internal/process/process_command.go。设得太低的风险llama-swap 会在优雅期结束后强制杀掉进程如果进程正处于关闭中途可能留下容器仍在运行、显存仍被占用的情况。因此凡是关闭缓慢的对象——容器、vLLM、任何通过cmdStop与其他守护进程通信的后端——都应该把unloadTimeout调高。批量卸载时Unload会按模型的unloadTimeout分桶先处理超时最短的一批避免一个长时间挂起的多节点卸载拖住后续快速卸载见 internal/router/base.go 的实现注释。Docker 场景必须配合 cmdStopllama-swap 直接拉起的进程是一个本地子进程在 Docker 部署中cmd里跑的docker run只是本地的 Docker 客户端进程真正运行模型的是容器内的服务进程。如果不加处理卸载时 llama-swap 只会终止本地的docker run客户端容器本身可能继续运行显存依旧被占用。解决办法是在模型上配置cmdStop让卸载动作真正落到容器上models: docker-llama: ttl: 600 cmdStop: docker stop ${MODEL_ID} unloadTimeout: 30一个容器模型的 10 分钟空闲卸载需要同时具备三个设置ttl: 600决定空闲多久触发卸载cmdStop: docker stop ${MODEL_ID}决定如何优雅停止容器unloadTimeout: 30给docker stop留足执行时间。cmdStop的底层执行逻辑见 internal/process/process_command.go进程收到停止信号时如果配置了CmdStop会先执行该命令其中${PID}占位符会被替换为实际进程 PID命令输出会被记录到进程日志有测试TestProcessCommand_CmdStopOutputLogged专门验证这一点见 internal/process/process_command_forking_test.go未配置CmdStop时Unix 平台默认对整个进程组发送 SIGTERMterminateProcessTree确保 shell 包装的 fork 子进程不会成为孤儿cmdStop命令本身同样受unloadTimeout限制在 goroutine 中执行超时后仍会走 SIGKILL 兜底路径保证卸载不会被一个挂起的停止命令无限阻塞。Windows 平台的默认cmdStop则是taskkill /f /t /pid ${PID}见 internal/config/model_config.go。按需手动卸载不需要等待 TTL随时可以主动卸载模型三个入口都指向同一套卸载逻辑$ curl http://localhost:8080/unload # 卸载全部 $ curl -X POST http://localhost:8080/api/models/unload # 卸载全部 $ curl -X POST http://localhost:8080/api/models/unload/qwen-coder # 卸载单个模型其中GET /unload由 internal/server/server.go 注册处理函数handleUnload只停止本地进程远端 peer 模型不受影响见 internal/server/api.goPOST /api/models/unload与POST /api/models/unload/{model...}由 internal/server/server.go 注册见 internal/server/apigroup.go卸载单个模型时会先做别名解析RealModelName模型不存在返回 404model not found模型存在但无本地服务器返回 404no local server found for requested model卸载全部/单个模型最终都调用s.local.Unload(0, ...)——timeout 0表示使用每个模型自身配置的unloadTimeout这正是前面配置项生效的路径。Web UI 的模型列表中每个模型都带有一个卸载按钮点击即调用同一端点前端实现见 ui/src/components/ModelLoadButton.svelte模型看板还提供全部卸载操作见 ui/src/routes/ModelsDash.svelte。如何为你的场景选择合适的值TTL 没有放之四海皆准的数值需要结合显存规模、模型加载成本与流量特征来权衡单 GPU、同一时刻只跑一个模型TTL 意义不大——换出操作本来就会把旧模型踢掉globalTTL: 0即可保持模型常驻直到被换出。多个模型常驻共存配合分组/矩阵路由参见 分组与矩阵路由指南TTL 是你从安静模型手中回收显存的主要手段从300–900 秒这个区间起步比较合理再按实际负载微调。加载缓慢的模型大权重、vLLM 等短 TTL 代价高昂——下一次请求要承受漫长的冷启动。这类模型应给长 TTL甚至直接ttl: 0让路由器只在必要时才换出它们。希望小模型始终热备ttl: 0搭配persistent分组persistent: true的分组成员不会被换出见 internal/router/group.go 与对应的持久分组不驱逐测试 internal/router/group_test.go。相关文档groups-and-matrix 分组与矩阵路由指南——控制哪些模型常驻一起运行kubeswap Kubernetes 部署示例——其中展示了unloadTimeout: 60配合cmdStoppod 终止的容器场景配置配置参考文档中reference/config/globalTTL与reference/config/unloadTimeout条目提供了更完整的参数定义赞分享后端API网关LLM 网关人工智能大模型本地部署【免费下载链接】llama-swapReliable model swapping for any local OpenAI/Anthropic compatible server - llama.cpp, vllm, etc项目地址https://gitcode.com/gh_mirrors/ll/llama-swap点击查看免费下载相关推荐LlamaGPT自定义模型教程加载第三方LLaMA模型完全指南LlamaGPT自定义模型教程加载第三方LLaMA模型完全指南 引言突破模型限制释放本地AI潜能 你是否受限于LlamaGPT默认提供的模型选择是否希望AI 应用大模型本地部署后端前端llama-swap 客户端兼容性与加载反馈详解sendLoadingState 与 includeAliasesInList 实战指南llama swap 客户端兼容性与加载反馈详解sendLoadingState 与 includeAliasesInList 实战指南 本文围绕 llama后端API网关LLM 网关人工智能大模型本地部署llama-swap 实战指南在本机多模型推理服务之间按需热切换llama swap 实战指南在本机多模型推理服务之间按需热切换 llama swap 是一个用 Go 编写的本地模型调度代理它让一台机器上的多个生成式 A后端API网关LLM 网关人工智能大模型本地部署上一篇mons完全指南用这个POSIX Shell脚本一键管理X显示器的终极教程下一篇掌握Blender与CAD协同工作3步实现工业级模型精度控制终极方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考