Skip to content

模型部署:Java 服务需要关心的那部分 ​

原来那套「用 TorchServe 或 Flask 把模型包成 HTTP 接口」的做法已经过时了——TorchServe 的仓库在 2025 年 8 月被归档,官方明确说明不再有更新、缺陷修复和安全补丁。现在的问题变成了:选托管 API、自建 vLLM 还是本地 Ollama,以及 Java 侧要为此做哪些准备。

一、先说结论 ​

  • 对大多数 Java 团队,托管 API 是默认选择:没有 GPU 运维、按用量付费、接口通常是 OpenAI 兼容的 HTTP。
  • 自建的主要理由是数据不能出网、或者用量大到自建更便宜,这时 vLLM 是当前的主流选择,它提供 OpenAI 兼容接口和连续批处理。
  • 本地 Ollama 适合开发和评测:一条命令拉起模型,接口同样兼容,但吞吐和并发能力有限。
  • 非 LLM 的传统模型(分类、排序、CV)仍然需要 Triton 这类推理服务框架,或者直接嵌入到 Python 服务里。
  • 无论哪种形态,Java 侧要处理的都是同一组问题:超时与重试、流式响应、并发上限、成本与配额、降级。

二、四种形态 ​

托管 API厂商负责一切自建 vLLMOpenAI 兼容接口本地 Ollama开发与小规模Triton 等推理框架多框架、非 LLM 模型按 token 计费自备 GPU单机、易上手运维成本最高无论哪种形态,Java 侧都要处理:超时与重试、流式响应、并发上限、成本与配额TorchServe 已于 2025 年 8 月归档,新项目不要再选它
图 1 · 对 Java 服务来说,四种形态的差别主要在「谁负责扩缩容与显存管理」,接口大多是 OpenAI 兼容的 HTTP
形态谁负责扩缩容与显存适合主要代价
托管 API(云厂商或模型厂商)服务方绝大多数业务场景按 token 计费;数据出网;速率限制
自建 vLLM自己数据不能出网、用量大、需要特定模型GPU 成本与运维;容量规划
本地 Ollama自己(单机)开发、演示、离线评测并发与吞吐有限
Triton 等推理框架自己非 LLM 模型、多框架混合部署配置复杂,运维成本最高

2.1 关于 TorchServe ​

PyTorch 官方仓库的说明是「Limited Maintenance——不再积极维护,没有计划中的更新、缺陷修复、新功能和安全补丁」,仓库已于 2025 年 8 月 7 日归档为只读。已有部署可以继续跑,但新项目不应该再选它;如果现有系统依赖它,要把迁移列进计划,至少要评估安全补丁缺失的风险。

2.2 为什么 vLLM 成了默认 ​

它解决的是 LLM 推理特有的两个问题:KV 缓存的内存管理(PagedAttention)和连续批处理(不同长度的请求动态组批)。对使用方来说,最直接的好处是暴露 OpenAI 兼容的 /v1/chat/completions 接口——Java 侧的客户端代码不需要为自建和托管写两套。

bash
# 典型启动方式(参数按显存与模型调整)
vllm serve <model> --max-model-len 8192 --gpu-memory-utilization 0.9

自建之前要算清楚三件事:显存够不够(模型权重 + KV 缓存)、并发上限是多少(超过就排队)、谁值班(GPU 节点故障、驱动升级、模型更新)。

三、Java 侧的接入要点 ​

无论后端是哪种形态,这些问题都要在 Java 服务里解决。

3.1 超时与重试 ​

模型调用的耗时分布与普通接口完全不同:p50 可能 1 秒,p99 可能 30 秒,长文本生成更久。

java
HttpClient client = HttpClient.newBuilder()
        .connectTimeout(Duration.ofSeconds(3))     // 连接快速失败
        .build();

HttpRequest request = HttpRequest.newBuilder(uri)
        .timeout(Duration.ofSeconds(60))            // 读超时要按生成长度设置
        .POST(...)
        .build();

重试要非常克制:生成类请求不是幂等的,重试会产生两次计费和两份不同的结果。可以重试的只有明确的网络错误和 429(限流),并且要用指数退避。

3.2 流式响应 ​

用户体验上,流式(SSE)几乎是必需的——首字延迟远小于整段生成时间。Java 侧要注意:

  • 响应是长连接,占用的是连接而不是线程(用异步或虚拟线程),见 虚拟线程迁移;
  • 中途断开要能取消上游请求,否则会白白消耗 token;
  • 网关、负载均衡器的缓冲和超时配置要允许长连接与分块传输。

3.3 并发与成本 ​

  • 给模型调用单独的线程池或信号量,不要和普通业务共用,避免慢调用拖垮整个服务。
  • 设置输入与输出的长度上限,这是成本控制最有效的手段。
  • 按用户或租户限流,防止单个调用方耗尽配额。
  • 记录每次调用的 token 数,成本要能按业务维度归因。

3.4 降级 ​

模型服务不可用或超时的时候,业务要能继续:返回兜底文案、跳过智能环节走原有流程、或者把请求放进队列稍后处理。不要让一个「智能摘要」功能挂掉整个页面。

3.5 评测与灰度 ​

换模型、改提示词都相当于一次发布,需要:

  • 固定的评测集:几十到几百条真实样例加期望结果,每次变更跑一遍;
  • 灰度:先放一小部分流量,对比关键指标(准确率、人工修正率、成本);
  • 可回滚:模型和提示词都应该是配置,不是硬编码。

四、常见误区 ​

  • 「先选个框架把模型包成接口」:TorchServe 已归档;LLM 直接用 vLLM 或托管 API,自己写包装层的理由越来越少。
  • 「自建一定更便宜」:要算上 GPU 常驻成本、运维投入和闲置率,低用量时托管通常更划算。
  • 「把超时设长一点就不会失败」:长超时会占满连接与线程,要配合流式与取消。
  • 「失败就重试」:生成类请求不幂等,重试意味着双倍成本和不一致的结果。
  • 「模型部署是算法团队的事」:接入层的超时、限流、降级、成本归因都在服务端这一侧。

小结 ​

模型部署对 Java 服务而言,本质上就是一个延迟高、成本按量计、偶尔不可用的下游依赖。选形态先看数据合规与用量:能用托管就用托管,必须自建就用 vLLM,本地开发用 Ollama。接入时把超时、流式、并发上限、成本归因和降级这五件事做全,剩下的模型细节可以交给算法侧。

Java 侧的工具调用与可控性设计,见 给 Java 服务接一个可控的 Agent。


参考资料

文章以 CC BY-NC-SA 4.0 授权 · 代码片段以 MIT 授权