最近我把 Qwen3.5 顺利跑进了函数计算平台,整个过程没有买服务器、没有装显卡驱动、没有手动配 CUDA,只做了几件很基础的事情:把推理镜像准备好、设置好模型路径、创建 HTTP 触发器。一个部署在云上的大模型推理服务就这么起来了。这篇文章不聊虚的,直接把我从选型、部署、调参到压测、排查的真实过程完整展开,给也想把大模型“一键变成服务”的朋友当一份实操参考。
1. 为什么非要用函数计算来跑大模型
1.1 传统部署方式的痛点
如果有过自己部署开源大模型的经验,应该知道这个流程有多折腾。你得先有一台带 GPU 的服务器,然后装 NVIDIA 驱动、配 CUDA、装 cuDNN、选 Python 版本、建虚拟环境、装 PyTorch、装推理框架,最后还要处理模型权重文件的下载和转换。环境的问题刚刚解决,服务暴露公网、做鉴权、做并发控制又来了。
更让人头疼的是成本。一台性能还过得去的 GPU 服务器,包月费用不低,而大多数场景下服务的调用量并不饱和。我见过不少团队或个人开发者,买了一台高端 GPU 机器,实际每天的调用可能只有几百次,大部分时间 GPU 都在空转。这就是传统部署模式最典型的矛盾:需求有明显的波峰波谷,但资源却必须按峰值采购。
自建 Kubernetes 集群也没好到哪里去。集群本身是高可用的,但工作节点、存储、网络插件、监控告警全要自己维护。为了跑一个推理服务,搭起一套完整的运维体系,这本质上是把问题从环境层面转移到了集群层面,复杂度不降反升。
1.2 函数计算模式的优势与适用场景
函数计算是一种事件驱动的计算形态。从使用者的角度看,你不需要关心底层服务器在哪里、是不是挂了、要不要升级,只需要关注“我的代码/容器怎么响应请求”。当你把大模型推理封装成一个自定义容器镜像后,平台会在请求到达时拉起实例,处理完请求后根据策略缩容,空闲时甚至可以缩到零。
这种模式解决了传统方案的两个核心问题:一是空闲成本,二是运维负担。低流量时实例收敛,不产生费用;高流量时平台自动扩容,不需要你预先规划机器数量。对我这种不想天天盯着服务器的人来说,吸引力非常大。
它的适用场景也很清晰:个人作品 Demo、内部工具、教学演示、调用量存在明显峰谷的 API 服务、需要快速验证模型效果的场景。不适合的场景也有,比如要求个位数毫秒响应的实时业务、超长时间保持的 WebSocket 长连接、被固定高并发打到每秒上千 QPS 的核心交易链路。这类场景更适合用常驻集群甚至裸金属方案。
2. 零配置部署前的硬性准备
2.1 账号与权限开通
所谓“零配置”并不是真的什么都不用做,而是把基础设施层面的配置交给平台。但在平台侧,你需要先完成几个必要的动作。
首先,要在控制台开通函数计算服务。开通过程中通常需要创建一个服务关联角色,授权函数计算访问容器镜像服务、对象存储、日志服务。角色授权的时候我建议保持最小权限原则:只给这个项目需要的权限,不要直接给个管理员权限了事。后面如果换了新项目,再单独配置,避免权限面过宽。
然后是镜像仓库。如果你打算用自定义镜像,必须先把镜像推送到平台可访问的镜像仓库里。这一步需要在本地或构建机上登录镜像仓库、打标签、推送。如果不想自己构建镜像,可以查看平台是否提供了预置的模型推理镜像,直接引用即可。
2.2 镜像与模型文件方案选型
部署 Qwen3.5 这类大模型时,第一个要决策的问题是模型文件放在哪。很多新手会尝试把模型直接打进镜像,这是个大坑。Qwen3.5 的权重文件动辄十几 GB,塞进镜像后镜像体积巨大,每次部署或冷启动都要拉取很长的数据,速度极慢,而且镜像构建和推送也非常痛苦。
合理的方案是:镜像只包含推理框架、依赖库和启动脚本,模型文件放在对象存储或平台的共享文件系统里。实例启动时,通过启动脚本把模型文件拉取到本地磁盘,然后启动推理服务。这样镜像能控制在几 GB 以内,模型文件也能独立更新,不需要重新构建镜像。
如果平台提供了大模型专用镜像,我建议直接用。这类镜像通常已经预装好推理框架、配置好了运行用户、暴露了正确的端口,你要做的只是填模型路径。我这次就是先试了模板镜像,成功跑通后再切换到自己定制的镜像,逐步加深控制。
2.3 环境变量与资源规格规划
不管用不用模板,环境变量都是必须规划好的。以常见的推理框架为例,需要设置下面几类:
- 模型相关:MODEL_NAME、MODEL_BASE_PATH、MODEL_LOAD_FORMAT
- 缓存相关:HF_HOME、TRANSFORMERS_CACHE、HUGGINGFACE_HUB_CACHE
- 服务相关:VLLM_SERVER_PORT、CONCURRENT_REQUESTS、GPU_MEMORY_UTILIZATION
这些变量决定了推理框架从哪里读模型、缓存放在哪、监听哪个端口。漏配任何一个,都可能出现“框架启动了但模型加载失败”或者“健康检查不通过”的情况。
资源规格的选择则要按模型参数量来算。Qwen3.5 如果是 7B 的 FP16 权重,模型本身需要约 14GB 显存,这还没算 KV Cache。因此对应实例显存至少要有 24GB 才稳妥。如果使用 INT4 或 INT8 量化版本,显存占用会降到 8GB 左右,16GB 显存的实例也能跑。内存方面,我一般选 16GB 或 32GB,磁盘选用性能型 SSD,容量至少 50GB,给模型文件和临时缓存留余量。
3. 一键部署完整实操记录
3.1 创建函数:从模板到自定义镜像
我这次是在函数计算控制台操作的,路径很直接。进入控制台后选择目标地域,点击创建函数。函数类型选择“自定义容器镜像”,如果能看到模板市场的话,也可以先找 Qwen3.5 推理模板一键创建。
以自定义镜像方式为例,关键步骤是:
- 填写函数名称,比如 qwen35-inference-demo。
- 选择容器镜像地址,填你推送到镜像仓库的镜像。
- 设置容器启动端口,推理框架默认监听 8000 端口,我就在这里填 8000。
- 配置启动命令。如果镜像的启动命令已经写好,可以不填;否则需要手动指定。
- 添加环境变量,把模型路径、缓存路径、并发参数都写进去。
- 申请 GPU 实例,选择显存和内存规格。
- 创建 HTTP 触发器,绑定到函数。
模板创建方式就更省事了,平台会预置一套完整配置,包括镜像、环境变量、监听端口和健康检查路径。通常只要填模型标识和资源规格就行。但模板隐藏了大量细节,如果后续想调优,还是要回到自定义配置里理解每一步的含义。
3.2 配置 GPU 与内存:参数选择背后的计算逻辑
部署大模型时,显存计算是绕不开的基本功。参数量 7B 意味着 70 亿个参数,每个参数用 FP16 存储占 2 字节,仅权重就是 14GB。推理过程中还要额外分配 KV Cache,它的大小跟并发度和上下文长度相关。上下文越长、并发越高,KV Cache 占用越大。
因此,一个最基本的经验值:7B 模型选 24GB 显存实例,14B 模型选 40GB 以上显存实例。如果预算有限,优先考虑量化模型把显存降下来,而不是硬选更大显存机器。量化版在精度损失可接受的情况下,能显著降低部署成本。
内存设置容易被忽略,但实际上模型加载时先落到内存,再加载到显存。内存太小会导致加载阶段直接 OOM。我一般让内存不小于显存的一半,保守一点直接 32GB。
3.3 设置触发器与域名:让模型对外提供服务
函数创建完成后,默认还不能直接好用,要配置对外访问入口。
需要创建一个 HTTP 触发器,选择允许访问的方法,至少包含 POST。触发器的调用路径要记住,它是后面发请求的基础。平台默认分配的域名通常带有端口或较长的路径,如果你想对外提供一个简单干净的接口地址,就需要绑定自定义域名。操作步骤是:在域名设置里添加域名,完成 DNS 解析,将域名指向平台提供的 CNAME 地址,等待证书生效。
配置好之后,我用 curl 做了第一次验证。命令大致是这样:
curl -X POST "https://your-domain.example.com/你的函数路径" \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen3.5-7B-Instruct", "messages": [ {"role": "user", "content": "你好,介绍一下你自己"} ], "max_tokens": 128 }'第一次调用时,因为还没有实例存在,函数计算会冷启动,响应等了比较久,但最终拿到了正常返回。那一刻整个链路算是彻底打通了。
4. 核心原理拆解:函数计算为什么能“按需拉起”大模型
4.1 冷启动与镜像缓存的博弈
函数计算的实例生命周期可以简单概括为:请求到达 -> 发现没有空闲实例 -> 创建新实例 -> 拉取镜像 -> 启动容器 -> 加载模型 -> 返回结果。
传统应用部署时,这些步骤只会在发布时发生一次,而函数计算把它平摊到每次扩容。最花时间的部分有两个:镜像拉取和模型加载。镜像如果只有几 GB,在平台内网拉取速度尚可,最怕的是模型文件也在镜像里,那冷启动时间就是灾难级。
平台为了缓解这个问题,通常会对热点镜像做缓存。同一个镜像在同一个地域被拉取过之后,后续新的实例可以直接从本地缓存加载,速度会快很多。但这是平台侧机制,你的代码无法直接干预你能做的是把冷启动时间尽量控制在模型加载这个不可压缩的环节上,把其他环节压到最低。
我实际测试中,第一次冷启动从发送请求到收到首个 token,大约花了 40 多秒。后续如果实例没有回收,热调用首 token 延迟在 300 毫秒左右;如果实例被回收再拉起,则又要回到 40 秒级。这个冷热差异非常明显,设计对外服务时必须考虑。
4.2 并发扩容与实例生命周期
当多个并发请求同时进来时,函数计算会创建多个实例。每个实例都会复制一份模型加载到显存里。这既是优势也是成本来源:优势是天然的隔离性和弹性,成本则是每个实例都要消耗同样的显存资源。
这里有两个关键参数:单实例并发度和实例上限。单实例并发度控制的是一个实例内最多同时处理多少个请求。对 GPU 推理服务来说,单实例并发度不宜太高。大模型推理的显存有一部分是 KV Cache,并发越高,KV Cache 总量越大,很容易把显存打爆。我一般设置单实例并发度为 2 到 4,具体要看模型大小和显存余量。
实例上限是一个成本保护参数,不设置的话平台理论上可能无限扩容。一定要设,而且要根据成本预算来设。比如你只会同时运行 4 个实例,那就把上限写成 4,无论流量多大都自动丢弃多余请求或排队,好过账单爆炸。
4.3 计费逻辑与成本兜底策略
函数计算的计费模型和传统云服务器完全不一样,它主要包含三块:请求次数、资源用量、公网流量。资源用量是整个计费的核心,按“内存大小 × GPU 规格 × 运行时间”累积计费。换句话说,实例运行得越久、规格越高,费用越高。
举个例子便于理解。假设你选了一台 24GB 显存、32GB 内存的实例,每次请求从模型加载(假设实例已存在)到生成完毕需要 20 秒,平均每天 1000 次请求,那每天累计资源时间为 20000 秒,也就是约 5.6 小时。按资源单价换算下来,每月的费用大致相当于这台实例连续运行 7 天的价格,但仍然远低于包月整机成本。
成本兜底策略我有三条建议:
- 设置实例上限,防止意外峰值把预算打穿。
- 为高流量时段购买预留实例,获得更低的单价和更快的冷启动。
- 给函数配置成本预算告警,用量超过阈值时及时通知。
5. 实测:接口调用、延迟与并发表现
5.1 基础调用测试
部署完成后,我做了几组测试,第一组是单请求基础调用。使用 OpenAI 兼容的请求体结构,返回也是标准的 chat completion 格式。我只改动 temperature 和 max_tokens 两个参数。
第一次测试的结果如下:总响应时间约 1.2 秒,其中首 token 延迟约 320 毫秒,然后开始流式输出内容。这个延迟在可接受范围,毕竟模型权重比较大,单次生成前需要先做 prefill 计算。如果不走流式,而是等完整结果一次性返回,总时间会随生成长度线性增长。比如生成 256 个 token,总耗时大约 3.5 到 4 秒。
如果你把生成长度拉长到 2048,实测延迟会明显上升,大概在 15 秒上下。这说明在函数计算上跑大模型,体验最自然的方式是启用 SSE 流式输出,让客户端一边接收、一边渲染,而不是傻等完整结果。
5.2 并发压测与性能数据
为了搞清楚这台“弹性 GPU 实例”的真实处理能力,我用了开源压测工具做了简单并发测试。工具本身叫 hey 或者 wrk 都行,原理都一样:并发发送请求,统计成功率、时延分布和 QPS。
我跑了三组测试,结果如下:
| 场景 | 并发数 | 平均时延 | QPS | 成功率 |
|---|---|---|---|---|
| 单个实例热调用 | 1 | 1.1s | 0.8 | 100% |
| 单个实例 4 并发 | 4 | 2.8s | 1.4 | 100% |
| 自动扩容 2 实例 | 8 | 2.1s | 3.5 | 98% |
需要注意,这个性能数据的前提是单实例并发度设为 2,每个请求生成 128 个 token。如果你改用更小的量化模型,或者限制 max_tokens,QPS 会有明显提升。实测中 4 并发时平均时延上涨明显,因为 GPU 计算排队了,但吞吐没有线性下跌,说明实例内部调度还有余量。
自动扩容到 2 个实例后 QPS 上升了,但成功率掉到 98%,原因是有个别请求因为冷启动超时被中断。压测期间如果实例是新建的,冷启动占了很长时间,压测工具默认超时时间较短就会误报失败。这里得到的经验是:做压测前先发几个预热请求,把实例拉起来再跑,数据才更有参考价值。
5.3 成本测算对比
我把自购 GPU 服务器和函数计算按量付费做了一个测算对比。假设模型是 Qwen3.5-7B,需要 24GB 显存,日请求量 5000 次,每次平均处理 20 秒,每日资源用量约 28 小时。按月计,整台 GPU 服务器的固定成本约是函数计算按量成本的 2 到 3 倍。
| 方案 | 月基础成本 | 额外成本 | 弹性能力 |
|---|---|---|---|
| 自购 GPU 服务器 | 固定包月 | 带宽、磁盘、运维人力 | 无,需手动扩容 |
| 函数计算按量 | 接近 0(无请求时不收费) | 按资源使用量累计 | 自动弹性 |
| 函数计算预留实例 | 有固定预留费用 | 单价更便宜 | 自动弹性 |
这张表说明一件事:如果你的调用量很稳定,预留实例模式是最好的;如果调用量忽高忽低,按量模式可以省下大量空闲成本。我自己会把两种模式结合起来:核心链路用预留实例保活,剩余流量走按量模式兜底。
6. 典型问题排查与避坑指南
6.1 镜像拉取失败或超时
我在第一次部署时就遇到镜像拉取一直卡住的情况。控制台上看到了“ImagePullBackOff”的提示,日志里显示拉取超时。原因是本地构建的镜像体积过大,超过了几 GB,平台在限定的启动时间内拉不完。
解决方案有几个方向:
- 把模型文件从镜像中拆出去,通过启动脚本从外部存储拉取。
- 将镜像推送到平台自带的镜像仓库,走内网拉取速度更快。
- 检查镜像架构是否匹配,不要在 ARM 机器上构建镜像然后部署到 x86 实例。
- 如果平台支持设置更长的启动超时,直接调大。
我最后是把基础镜像换成更精简的操作系统,只保留推理框架需要的运行库,镜像从 8GB 降到了 2.5GB,拉取问题彻底消失。
6.2 显存不足与推理超时
实例启动后模型加载到一半就报错退出,再去日志里看发现写着 CUDA out of memory。这是因为模型权重加上 KV Cache 超出了实例显存。解决办法不是盲目换更大的实例,而是先检查你的量化精度和上下文长度。
我遇到的情况是上下文长度参数设成了 32768,KV Cache 在并发 2 的需求下占用太大,直接撑爆了。后来把 max-model-len 调整到 8192,并把 GPU 显存利用率从 0.9 降到 0.85,问题解决。这个参数不是越大越好,一定要结合显存和并发去算。
推理超时又是另一个典型问题。函数计算默认的函数执行超时时间是 10 秒,而加载大模型加上首 token 生成可能就超过这个时间。需要手动把执行超时设成 300 秒甚至更大。但这个值不宜设得过大,因为超时时间就是计费窗口的上限,设得越大越容易造成意外扣费。
6.3 自定义域名与连接类型限制
自定义域名绑定本身不难,但容易踩坑的有两处。一是 DNS 解析生效需要时间,不值得反复刷新页面去检查,等几分钟再用 ping 验证比较稳。二是函数计算对长连接的支持有限,如果你计划用 WebSocket 做流式对话,就要提前确认平台是否支持,不支持的话果断改用 SSE。
HTTP 触发器对请求头和响应头有一些限制,例如响应头不能随意修改,自定义头会被过滤。如果你的客户端依赖特殊的 Header 传递鉴权信息,建议使用 API 网关产品接在函数前面,由网关控制 Header 透传和鉴权,这比我手动处理舒服得多。
6.4 服务冻结与冷启动优化
函数计算在实例空闲一段时间后会回收实例,这是成本优化的核心机制,但也带来了“冷启动焦虑”。第一次请求的用户可能要等上几十秒,这是很多人不习惯的。解决套路有几种:
- 预留实例:平台提前拉起指定数量的实例并保持热状态,调用时直接命中。
- 定时预热:用定时触发器每几分钟发一个健康检查请求,让实例保持存活。
- 模型缓存:把模型文件放在平台共享文件系统或加速缓存里,实例重建时不需要重新下载。
定时预热是我目前最常用的方式,成本最低。缺点是实例会一直保持运行,会产生资源费用,如果调用量本身就低,预热成本可能超过按量调用的成本。划不划算要自己算一笔账。
7. 个人经验与后续扩展建议
7.1 我在实际项目中踩过的坑
第一批实战经验里,有几个教训非常深刻。
第一次部署时,我为了图省事,直接把模型权重塞进了容器镜像,镜像打出来 20 多 GB,上传花了一个多小时。更尴尬的是后面每次修改代码都要重新推送镜像,整个迭代速度被拉得很低。后来改成启动时从对象存储拉取模型,用平台的文件缓存做二次加速,迭代速度才正常。
还有一次是因为环境变量漏配,导致推理框架找不到 tokenizer,服务能启动但接口全部报错。这个问题很隐蔽,因为日志里不会直接写“环境变量缺失”,只会报找不到某个文件。排查了半天才想起来对比模板里的环境变量列表。现在我的做法是先把模板环境变量全部列出,逐个确认有没有依赖,再手动创建自定义函数。
压测阶段也翻过车。当时把单实例并发度设成了 8,结果 8 个并发请求同时进来,显存瞬间被打爆,实例直接崩溃。还好只是测试环境,不然服务就雪崩了。从那以后我明确了一条原则:大模型推理服务的并发度必须经过显存计算和压测验证,不能拍脑袋。
7.2 从一键部署到生产级服务的三条扩展路径
如果你验证完“函数计算跑 Qwen3.5”这条路是通的,下一步想从 Demo 变成生产服务,我建议沿着三条路径往下走。
路径一是接入 API 网关。函数计算的 HTTP 触发器本身不带复杂的鉴权、限流能力,网关可以补齐这块。把公网入口从函数触发器改成网关,在网关层做 API Key、签名校验、IP 黑白名单和限流,函数内部可以专注推理逻辑。
路径二是模型文件仓库化。把不同版本的 Qwen3.5 权重文件统一放在对象存储或共享文件系统里,通过环境变量的切换来发布不同模型版本。这样既能做到模型热更新,又不需要为每个模型单独构建一个函数。
路径三是建立可观测体系。大模型推理服务比普通 API 更依赖监控数据,你需要知道每个请求的 TTFT(首 token 时间)、生成长度、显存峰值、实例扩缩容次数等信息。把这些信息打到日志系统和监控平台里,才能做真正的容量规划。
从我个人的角度说,函数计算跑大模型最舒服的地方在于:它把计算资源变成了一个可以随时被“唤醒”的东西。需要的时候它在,不需要的时候它消失,而账单也跟着你真实的用量走。这种模式带来的思维方式转变很奇怪,你会开始习惯从“我要多少台机器”变成“我这个请求值多少钱”。如果你正在考虑怎么把手里的模型低成本变成可用服务,这套方案值得在你自己的项目里亲手试一次。