第1777篇:开源模型的私有化部署成本分析——Ollama vs vLLM的TCO对比
第1777篇:开源模型的私有化部署成本分析——Ollama vs vLLM的TCO对比
很多团队在讨论"要不要自己部署开源模型"时,最终都卡在一个问题上:到底多少请求量才值得自建?
这个问题没有通用答案,因为它取决于太多变量:用什么机器、跑什么模型、并发量多少、维护成本算不算进去。
但大部分网上的分析要么太粗糙(只算GPU买多少钱),要么太学术(各种参数推导但不实用)。我来做一个偏工程实战的TCO(Total Cost of Ownership,总拥有成本)分析,用Ollama和vLLM这两个最常见的方案来做对比。
Ollama vs vLLM:先搞清楚定位
这两个工具经常被放在一起比,但其实定位不完全相同。
Ollama:开发者工具,重视易用性。一键安装,一行命令拉模型,API风格简洁。适合开发测试、小规模内部工具、个人项目。并发能力弱,大并发下性能明显下降。
vLLM:工业级推理框架,重视吞吐量和效率。支持 PagedAttention 等先进技术,并发能力强,可以部署在 Kubernetes 上做水平扩展。配置复杂,学习曲线陡,适合生产环境高并发场景。
简单判断标准:
- 开发验证 / 内部小工具 / 日请求量 < 1万次 → Ollama够用
- 对外服务 / 并发用户多 / 日请求量 > 1万次 → 考虑vLLM
硬件成本基准
我用三个典型硬件配置来分析,覆盖从低成本到高性能:
配置A:消费级GPU(RTX 4090)
- GPU:NVIDIA RTX 4090,显存24G
- 购买价格:约1.6万元
- 可运行模型:Qwen2.5-7B(全精度)、Qwen2.5-14B-Q4量化
- 适合:开发测试、低并发场景
配置B:入门级数据中心GPU(A10G)
- GPU:NVIDIA A10G,显存24G,云上约5000元/月(单卡)
- 可运行模型:同上,但驱动和稳定性更好
- 适合:生产环境小规模部署
配置C:高端数据中心GPU(A100 80G)
- GPU:NVIDIA A100 SXM4 80G
- 云上约24000元/月(单卡)
- 可运行模型:Qwen2.5-72B全精度、多模型并发
- 适合:大规模生产环境
Ollama的完整成本分析
部署与配置
Ollama部署极简:
# 安装
curl -fsSL https://ollama.ai/install.sh | sh
# 拉取模型
ollama pull qwen2.5:7b
ollama pull qwen2.5:14b-instruct-q4_K_M
# 启动服务(允许外部访问)
OLLAMA_HOST=0.0.0.0 ollama serveJava调用Ollama:
@Service
@Slf4j
public class OllamaService {
@Value("${ollama.base-url:http://localhost:11434}")
private String baseUrl;
private final RestTemplate restTemplate;
public OllamaService() {
// 设置超时,避免长时间阻塞
HttpComponentsClientHttpRequestFactory factory =
new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(120000); // 生成可能需要较长时间
this.restTemplate = new RestTemplate(factory);
}
/**
* 非流式调用
*/
public String chat(String model, String systemPrompt, String userMessage) {
Map<String, Object> request = new LinkedHashMap<>();
request.put("model", model);
request.put("stream", false);
request.put("messages", List.of(
Map.of("role", "system", "content", systemPrompt),
Map.of("role", "user", "content", userMessage)
));
request.put("options", Map.of(
"temperature", 0.7,
"num_ctx", 4096, // context window
"num_predict", 1024 // max output tokens
));
try {
ResponseEntity<Map> response = restTemplate.postForEntity(
baseUrl + "/api/chat", request, Map.class
);
Map message = (Map) response.getBody().get("message");
return (String) message.get("content");
} catch (Exception e) {
log.error("Ollama调用失败: model={}", model, e);
throw new RuntimeException("Ollama调用失败: " + e.getMessage(), e);
}
}
/**
* 并发性能测试
*/
public void benchmarkConcurrency(String model, int concurrency, int totalRequests) {
ExecutorService executor = Executors.newFixedThreadPool(concurrency);
AtomicLong successCount = new AtomicLong(0);
AtomicLong failCount = new AtomicLong(0);
AtomicLong totalLatencyMs = new AtomicLong(0);
long startTime = System.currentTimeMillis();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < totalRequests; i++) {
futures.add(CompletableFuture.runAsync(() -> {
long reqStart = System.currentTimeMillis();
try {
chat(model, "你是一个助手", "用一句话总结人工智能的定义");
successCount.incrementAndGet();
totalLatencyMs.addAndGet(System.currentTimeMillis() - reqStart);
} catch (Exception e) {
failCount.incrementAndGet();
}
}, executor));
}
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
long totalTime = System.currentTimeMillis() - startTime;
long successCnt = successCount.get();
log.info("Ollama并发测试结果: model={}, concurrency={}, total={}", model, concurrency, totalRequests);
log.info("成功: {}, 失败: {}, 总耗时: {}ms", successCnt, failCount.get(), totalTime);
log.info("QPS: {:.2f}, 平均延迟: {}ms",
(double) successCnt / totalTime * 1000,
successCnt > 0 ? totalLatencyMs.get() / successCnt : 0);
executor.shutdown();
}
}Ollama性能基准(实测数据)
在RTX 4090上运行 Qwen2.5-7B,测试简单文本分类任务(约500 input tokens,50 output tokens):
| 并发数 | QPS | 平均延迟(ms) | P99延迟(ms) |
|---|---|---|---|
| 1 | 2.1 | 476 | 520 |
| 4 | 3.8 | 1050 | 1800 |
| 8 | 4.2 | 1900 | 5200 |
| 16 | 4.1 | 3900 | 12000 |
Ollama的关键问题:并发性能差。并发超过8之后,QPS不再增加,但延迟急剧增加。这是Ollama的架构决定的,它不是为高并发设计的。
vLLM的完整成本分析
vLLM的安装比Ollama复杂,但值这个代价。
# 安装
pip install vllm
# 启动服务(OpenAI兼容接口)
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--gpu-memory-utilization 0.90 \
--max-model-len 8192 \
--tensor-parallel-size 1 \
--dtype bfloat16Java调用vLLM(与OpenAI接口兼容):
@Service
public class VLLMService {
@Value("${vllm.base-url:http://localhost:8000}")
private String baseUrl;
// vLLM兼容OpenAI接口,可以直接用OpenAI SDK
private OpenAIClient client;
@PostConstruct
public void init() {
// 配置指向本地vLLM
this.client = OpenAIClient.builder()
.baseUrl(baseUrl + "/v1")
.apiKey("not-needed") // vLLM本地部署不需要API Key
.build();
}
public String chat(String systemPrompt, String userMessage) {
ChatCompletionRequest request = ChatCompletionRequest.builder()
.model("Qwen/Qwen2.5-7B-Instruct")
.addMessage(ChatMessage.system(systemPrompt))
.addMessage(ChatMessage.user(userMessage))
.maxTokens(1024)
.temperature(0.7)
.build();
ChatCompletion response = client.chat().completions().create(request);
return response.getChoices().get(0).getMessage().getContent();
}
/**
* vLLM指标监控(Prometheus格式)
*/
public VLLMMetrics getMetrics() {
// vLLM暴露/metrics端点
String metrics = restTemplate.getForObject(baseUrl + "/metrics", String.class);
return parsePrometheusMetrics(metrics);
}
}vLLM性能基准(实测数据,同样硬件RTX 4090)
Qwen2.5-7B,同样的文本分类任务:
| 并发数 | QPS | 平均延迟(ms) | P99延迟(ms) |
|---|---|---|---|
| 1 | 2.3 | 435 | 480 |
| 8 | 12.5 | 640 | 1200 |
| 16 | 18.2 | 880 | 2100 |
| 32 | 22.1 | 1450 | 4500 |
| 64 | 21.8 | 2940 | 8000 |
vLLM的并发能力远强于Ollama,同样的硬件,vLLM的QPS是Ollama的5倍以上。这就是PagedAttention的价值所在。
TCO完整对比模型
我来建一个TCO计算模型,以一年为周期:
public class TCOCalculator {
/**
* 计算私有部署一年的总拥有成本
*/
public TCOReport calculate(DeploymentConfig config) {
// 1. 硬件成本
BigDecimal hardwareCost;
if (config.isCloudGPU()) {
// 云GPU按月租用
hardwareCost = config.getMonthlyGpuCostCny().multiply(new BigDecimal(12));
} else {
// 自购GPU,按3年折旧,第一年摊销1/3
hardwareCost = config.getGpuPurchaseCostCny()
.divide(new BigDecimal(3), 2, RoundingMode.HALF_UP);
}
// 2. 电费
// GPU TDP × 利用率 × 24h × 365天 × 电价
BigDecimal powerCostCny = config.getGpuTdpKw()
.multiply(config.getAvgUtilization())
.multiply(new BigDecimal(8760)) // 一年小时数
.multiply(config.getElectricityPriceCny()); // 元/度
// 3. 维护人力成本
// 估算:部署 + 日常维护 + 故障处理,月均约0.3个工程师工时
BigDecimal maintenanceCostCny = config.getEngineerMonthlySalaryCny()
.multiply(new BigDecimal("0.3")) // 0.3人月/月
.multiply(new BigDecimal(12));
// 4. 软件/工具成本(监控、日志等)
BigDecimal softwareCostCny = new BigDecimal(12000); // 约1000元/月
// 5. 合计
BigDecimal totalCostCny = hardwareCost
.add(powerCostCny)
.add(maintenanceCostCny)
.add(softwareCostCny);
// 6. 计算每1000个Token的成本
// 一年可以处理多少token:QPS × 平均token/请求 × 秒数 × 利用率
long annualRequestCount = (long)(config.getMaxQps()
* config.getAvgUtilization().doubleValue()
* 365 * 24 * 3600);
long annualTokenCount = annualRequestCount * (config.getAvgInputTokens() + config.getAvgOutputTokens());
BigDecimal costPerKToken = totalCostCny
.divide(new BigDecimal(annualTokenCount / 1000), 6, RoundingMode.HALF_UP);
return TCOReport.builder()
.hardwareCostCny(hardwareCost)
.powerCostCny(powerCostCny)
.maintenanceCostCny(maintenanceCostCny)
.softwareCostCny(softwareCostCny)
.totalAnnualCostCny(totalCostCny)
.annualRequestCapacity(annualRequestCount)
.annualTokenCapacity(annualTokenCount)
.costPerKTokenCny(costPerKToken)
.build();
}
}私有部署 vs 云端API的盈亏平衡点
用上面的模型算一个具体例子:
场景:用 Qwen2.5-7B 做文本分类,平均每次请求 500 input tokens + 50 output tokens
私有部署方案(vLLM + A10G云GPU):
- GPU租用:约5000元/月
- 电费(云上含在GPU费里)
- 维护成本:约3000元/月(0.3人月)
- 软件成本:约500元/月
- 月总成本:约8500元
- 最大QPS:约15(A10G跑7B模型)
- 月最大请求量:15 × 30 × 24 × 3600 × 0.6(利用率)= 约2333万次
API方案对比(GPT-4o-mini):
- 每次请求成本:500×$0.00015/1000 + 50×$0.0006/1000 = $0.000075 + $0.00003 = $0.000105
- 约0.00075元/次(按7元/美元)
- 月2333万次的成本:2333万 × 0.00075 = 约17500元
结论:月请求量超过约1000万次时,私有部署比GPT-4o-mini便宜。
如果换成更便宜的API(如 Deepseek 或 Qwen 云上API),盈亏平衡点会更高,私有部署的优势缩小。
什么情况下强烈建议私有化
除了成本,还有几种情况私有化是必选而非可选:
1. 数据不能出境(医疗、金融、政府):合规要求比成本更重要。
2. 网络延迟敏感:某些实时性要求极高的场景(如实时语音),云端API的网络延迟是致命的,本地推理能把延迟降到几十毫秒。
3. 需要深度定制:比如需要给模型加特殊解码逻辑、自定义停止词、特殊的输出格式控制,这些云端API支持有限,vLLM可以随意改。
4. 断网场景:有些工业场景是局域网环境,根本连不上外网。
一个容易忽略的坑:维护成本
很多团队的TCO分析只算硬件,忘了维护成本。私有化部署实际上是在引入一套新的基础设施:
- 模型更新要有流程(测试、灰度、回滚)
- 服务挂了要快速恢复
- 推理速度慢了要排查(显存碎片化、模型加载异常)
- 系统升级可能导致不兼容
我们的经验:中小团队做私有化,至少要有一个工程师能全职投入维护,否则维护成本会远超估算。
如果团队没有这个资源,建议老老实实用云端API,把精力放在业务上。
