双卡 A100 上如何给 Ollama 做轮询分发与健康检查,真正把吞吐跑满
一、为什么双实例比“一个实例看见两张卡”更适合吞吐优先场景如果你的模型能完整装进单张 A100那么对“整机总吞吐”来说双实例双端口往往比“单实例双卡自动调度”更直观、也更好控。原因很简单你把11434固定给 GPU0把11435固定给 GPU1请求层再做轮询这样两张卡会各自维护一份模型副本各自处理一部分流量。Ollama 的 API 本身就是本地 HTTP 服务天然适合被上层反向代理接入。(Ollama 文档)这套思路的核心不是“花哨”而是可控。单实例跨卡更适合“模型太大单卡放不下”双实例更适合“模型能单卡放下但我要吃满整机并发”。一旦你用轮询把流量稳定摊到两个实例上双卡就不再是“理论资源”而会变成真正可被业务吞掉的吞吐能力。这个判断是基于 Ollama 的本地 API 形态和多实例部署方式做出的工程化设计。(Ollama 文档)二、最小可用架构11434 11435 一个入口层推荐的结构非常简单ollama-gpu0127.0.0.1:11434ollama-gpu1127.0.0.1:11435一个统一入口Nginx 或 HAProxy业务系统只调用统一入口地址这样做的好处是业务代码永远只认一个入口而后端两个 Ollama 实例可以独立重启、独立摘除、独立预热。只要入口层健康检查配置合理一个实例挂了流量会自动被送到另一个实例。HAProxy 官方文档明确把健康检查定义为“只让健康服务器保留在负载均衡轮转中”Nginx 也支持 upstream 服务器组并能基于失败次数与超时做被动摘除。(HAProxy Technologies)三、先别急着上 Nginx先把两个实例本身验证通反向代理只是“调度层”前提是你的两个 Ollama 实例都能独立工作。先分别检查curlhttp://127.0.0.1:11434/api/versioncurlhttp://127.0.0.1:11435/api/version/api/version是最轻量的可达性检查接口适合拿来做存活探测如果你想看当前实例内存里有没有已经装载的模型就查/api/ps。这两个接口都属于官方 API。(Ollama 文档)再分别试一条最小生成请求curlhttp://127.0.0.1:11434/api/generate-d{ model: gemma3, prompt: 你好, stream: false }curlhttp://127.0.0.1:11435/api/generate-d{ model: gemma3, prompt: 你好, stream: false }Ollama 的/api/generate接口要求至少提供model和promptstream默认为true压测或联调阶段把它设成false更方便看完整返回。响应里还会带上total_duration、load_duration、eval_count、eval_duration等指标这些字段非常适合做性能分析。(Ollama 文档)四、为什么“预热”是双实例吞吐稳定的关键很多人在压测时发现一个很奇怪的现象第一批请求慢后面快或者两台实例里总有一台突然比另一台慢一大截。问题往往不在显卡而在模型装载与预热。Ollama 官方 FAQ 明确提到你可以通过发送一个“空请求”来预加载模型这对/api/generate和/api/chat都生效。也就是说在正式接流量之前先对11434和11435各打一遍预热请求让两边都把模型拉进内存再开始分流首包延迟会明显更稳定。(Ollama 文档)例如curlhttp://127.0.0.1:11434/api/generate-d{model:gemma3}curlhttp://127.0.0.1:11435/api/generate-d{model:gemma3}如果你本身已经配置了OLLAMA_KEEP_ALIVE-1那预热效果会更明显因为模型不会很快被卸掉。这样做的本质就是把“第一次装载的代价”提前支付掉而不是让真实用户帮你承担。相关预热方式来自官方 FAQ模型常驻则来自运行参数设计。(Ollama 文档)五、入口层选型Nginx 够轻HAProxy 更像“正经负载均衡器”1Nginx 的优点Nginx 非常适合已经在线上普遍使用它的团队。它的upstream机制可以定义后端服务器组再通过proxy_pass统一转发。官方文档说明Nginx 支持多种负载分发方式其中最常见的就是默认轮询同时max_fails和fail_timeout可以让后端在连续失败后被暂时标记为不可用。(Nginx)2Nginx 的限制很多人以为 Nginx 开源版就能直接做完整主动健康检查其实不是。ngx_http_upstream_hc_module这个“周期性主动健康检查”模块是商业订阅版本才有开源常见做法更多是依赖被动失败摘除也就是通过真实请求失败次数来判断后端是否有问题。(Nginx)3HAProxy 的优点如果你更看重“负载均衡本身”HAProxy 会更像专业工具。它原生支持健康检查官方文档明确说明健康检查的目的是确保只有健康服务器保留在轮转中而且balance可以选择roundrobin、leastconn等算法。对于 Ollama 这种长连接不算多、但单请求较重的推理服务roundrobin往往足够简单有效如果你更关心当前连接数均衡可以考虑leastconn。(HAProxy Technologies)六、Nginx 方案最小够用版如果你已经有 Nginx只想快速把两台 Ollama 实例挂起来这样配就够用了upstream ollama_backend { server 127.0.0.1:11434 max_fails3 fail_timeout10s; server 127.0.0.1:11435 max_fails3 fail_timeout10s; keepalive 32; } server { listen 8080; server_name _; location / { proxy_pass http://ollama_backend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header Connection ; proxy_connect_timeout 3s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }这套配置的含义是把两个 Ollama 实例放进一个 upstream 组由 Nginx 在它们之间分流如果某个后端在fail_timeout期间连续失败达到max_fails次就会被临时视为失败节点。Nginx 官方文档对upstream、max_fails、fail_timeout的语义都有明确说明。(Nginx)这里有个实战建议Nginx 适合“已经有它”的环境不适合把所有高级健康检查幻想都压在它身上。如果你只是想快速把两个 Ollama 实例挂成一个统一入口它很方便但如果你要更明确的主动健康检查、熔断、重试与状态可视化HAProxy 往往更省心。这个判断基于两者官方文档展示的能力边界。(Nginx)七、HAProxy 方案更像生产级标准答案如果让我给“双 A100 双实例 Ollama”选一个更顺手的生产入口我会更偏向 HAProxy。原因不是它“更高级”而是它对后端健康检查和负载均衡这件事更聚焦。一个很实用的配置可以这样写global log /dev/log local0 maxconn 10000 defaults mode http log global option httplog timeout connect 5s timeout client 300s timeout server 300s retries 2 frontend ollama_front bind *:8080 default_backend ollama_back backend ollama_back balance roundrobin option httpchk GET /api/version http-check expect status 200 server gpu0 127.0.0.1:11434 check inter 3s fall 2 rise 2 server gpu1 127.0.0.1:11435 check inter 3s fall 2 rise 2这里最关键的是两点第一balance roundrobin会让请求轮流打到gpu0和gpu1。HAProxy 官方文档写得很明确后端默认就是共享工作负载且支持roundrobin、leastconn等算法。(HAProxy Technologies)第二check会对后端做健康检查而option httpchk GET /api/version则把健康检查请求定向到 Ollama 的GET /api/version接口。HAProxy 官方文档对健康检查的定义非常清晰不健康的服务器会被移出负载均衡轮转。(HAProxy Technologies)如果你问我为什么不是拿/api/generate来做健康检查因为那太重了。/api/version返回轻、快而且足够验证进程是否正常提供 HTTP API真正的“模型是否已预热”可以通过独立预热脚本和/api/ps来辅助判断。(Ollama 文档)八、健康检查应该检查什么别一上来就查“最重的接口”这是很多推理服务最容易配错的地方。第一层进程存活检查/api/version即可。它轻量、简单、返回快适合高频探测。官方 API 提供该接口。(Ollama 文档)第二层模型是否已装载检查/api/ps。它能返回“当前已加载到内存的模型列表”适合用于预热完成后的巡检。官方 API 里就有这个接口。(Ollama 文档)第三层推理链路是否真的可用这层不要用高频健康检查做而应该用低频巡检或业务级探测比如每隔一段时间打一条极短的/api/generate请求验证模型能否在可接受时延内返回。因为/api/generate返回里自带total_duration、load_duration、eval_duration等指标非常适合用于“慢病监控”但不适合每秒钟高频打。(Ollama 文档)一句话总结就是存活用/api/version装载用/api/ps性能用/api/generate指标这样既不会把健康检查本身搞成负担也能把实例状态看得比较完整。相关接口能力都来自官方 API 文档。(Ollama 文档)九、如何判断“是不是已经把双卡真的吃起来了”只看到两个服务running还不够。你要确认的是两个实例都在接流量两个实例都装了模型模型没有明显 offload 到 CPU每个请求的负载分布基本均衡先查各自的模型装载情况curlhttp://127.0.0.1:11434/api/pscurlhttp://127.0.0.1:11435/api/ps然后用ollama ps看本机当前模型状态。Ollama 的上下文长度文档明确建议为了更好的性能应避免把模型 offload 到 CPU并通过ollama ps里的PROCESSOR字段确认是否为100% GPU。(Ollama 文档)再配合nvidia-smi观察两张卡的显存与利用率watch-n1nvidia-smi如果轮询正常、预热正常、请求量足够你会看到两张卡都在持续吃显存和算力而不是只有一张卡承担绝大多数请求。十、调用侧别写死单端口做一个最朴素的客户端分流就够了很多团队其实不一定非要上 Nginx 或 HAProxy。你完全可以在调用侧自己做一个非常朴素的分流器比如轮询11434和11435失败时自动切到另一边。这种方式的优点是轻量缺点是健康检查和摘除逻辑要自己写。最简单的 Python 伪代码大概是这样importitertoolsimportrequests ENDPOINTSitertools.cycle([http://127.0.0.1:11434,http://127.0.0.1:11435,])defgenerate(prompt,modelgemma3):last_errorNonefor_inrange(2):basenext(ENDPOINTS)try:rrequests.post(f{base}/api/generate,json{model:model,prompt:prompt,stream:False},timeout300,)r.raise_for_status()returnr.json()exceptExceptionase:last_erroreraiselast_error这样做的底层依据是Ollama 运行后 API 自动可用而/api/generate是标准生成接口如果你更偏向兼容现有 SDKOllama 还提供 OpenAI 兼容接口base_url指向http://localhost:11434/v1即可。(Ollama 文档)如果你已经有一套 OpenAI SDK 代码那么接入双实例时可以把 “目标 base_url” 做成可切换配置如果你前面挂了 HAProxy那业务端甚至不用感知后端有两台 Ollama。Ollama 的 OpenAI 兼容能力来自官方文档。(Ollama 文档)十一、别盲目把上下文拉大吞吐优先和长上下文优先是两回事很多人想“性能拉满”第一反应就是把OLLAMA_CONTEXT_LENGTH拉到很大。这个思路并不总对。Ollama 的上下文长度文档强调为了获得更好性能应尽量使用模型支持的合适上下文长度并避免 CPU offload同时也建议通过ollama ps检查实际分配的上下文和处理器分布。(Ollama 文档)对双实例吞吐优先场景来说8192 或 16384 这类更克制的上下文往往更合理。因为你追求的是“单位时间处理更多请求”不是“单请求尽量塞进最长历史”。如果你的业务真的是 Agent、长文分析、超长代码理解再单独给这类服务起长上下文实例会更科学。这个结论是结合官方对上下文与性能关系的建议做出的工程化取舍。(Ollama 文档)十二、如何做性能观测不要只盯着显卡利用率显卡利用率只是结果不是全貌。真正有用的观测应该至少包括三类1API 返回指标/api/generate的响应里有total_duration、load_duration、prompt_eval_count、prompt_eval_duration、eval_count、eval_duration。这些字段能告诉你到底慢在装载、慢在提示词处理还是慢在生成本身。(Ollama 文档)2模型装载状态/api/ps能看到当前实例内有哪些模型在内存里。这个接口特别适合判断预热是不是掉了、实例是不是偷偷卸载了模型。(Ollama 文档)3实例可达性与版本/api/version是最轻量的可达性接口很适合接到反向代理健康检查也适合外部巡检脚本快速探测。(Ollama 文档)所以别再只看nvidia-smi。真正能帮你定位瓶颈的是“API 时延 模型装载 GPU 状态”三件套。十三、一个很实用的预热与巡检脚本你可以在服务启动后跑一遍下面这种逻辑#!/usr/bin/env bashMODELgemma3forportin1143411435;doechocheck version on${port}curl-sfhttp://127.0.0.1:${port}/api/version||exit1echopreload${MODEL}on${port}curl-sfhttp://127.0.0.1:${port}/api/generate\-d{\model\:\${MODEL}\}/dev/null||exit1echocheck running models on${port}curl-sfhttp://127.0.0.1:${port}/api/psdone这个脚本背后的逻辑完全来自官方接口能力/api/version做轻探活空的/api/generate请求做预热/api/ps看是否已装载完成 (Ollama 文档)如果你用 systemd 管理两个 Ollama 服务还可以把这个脚本挂到服务启动后的初始化流程里确保实例在被接流量前就已经热起来。十四、最终建议两种常见生产打法打法一简单稳定型双实例11434、11435Nginx 做统一入口被动失败摘除启动后预热业务端只认一个入口这种方案部署快改造少适合已经有 Nginx 的环境。Nginx 的 upstream 和失败摘除语义来自官方文档。(Nginx)打法二更像专业负载均衡型双实例11434、11435HAProxy 做统一入口httpchk GET /api/versionroundrobin或leastconn独立预热脚本业务端只认 HAProxy 入口这种方案更适合你明确在做 API 服务且希望健康检查、摘除和分流行为更可控。HAProxy 的健康检查与后端算法能力来自官方文档。(HAProxy Technologies)如果让我只给一个结论我会说双卡 A100 上要把 Ollama 吞吐跑满最关键的不是“把参数调多猛”而是“让两个实例持续稳定地接到差不多的流量”。十五、结尾到了这一步双卡 A100 的部署才算真正从“会启动”进入“能打仗”。前面的安装、权限、端口冲突解决的是“服务起来”这一篇的轮询、健康检查、预热、性能观测解决的是“服务跑稳”。只有这两部分合在一起你的双卡机器才不是一个昂贵的摆设而是一台真正可持续输出吞吐的推理节点。Ollama 的本地 API、预热方式、运行模型查询、性能指标、OpenAI 兼容接口再加上 Nginx 或 HAProxy 的分发与健康检查能力已经足够支撑一套很实用的本地生产方案。(Ollama 文档)