嵌入SGLang的RAG服务中调用embedding接口返回401的API Key校验逻辑排查

文章导读
在 RAG 服务通过 SGLang 提供的 OpenAI 兼容接口调用 embedding 时,收到 401 说明请求在进入模型推理前就被鉴权层拦截。这里要先分清拦截发生在 SGLang 服务本身,还是 RAG 服务与 SGLang 之间的网关/代理;直接对 SGLang 发一个最小请求,是最快的分界方法。
📋 目录
  1. A 先把 401 分层定位
  2. B 核对 SGLang 的 API Key 开关
  3. C 确认 RAG 服务实际发出去的请求头
  4. D 按清单收口,避免反复试错
A A

在 RAG 服务通过 SGLang 提供的 OpenAI 兼容接口调用 embedding 时,收到 401 说明请求在进入模型推理前就被鉴权层拦截。这里要先分清拦截发生在 SGLang 服务本身,还是 RAG 服务与 SGLang 之间的网关/代理;直接对 SGLang 发一个最小请求,是最快的分界方法。

排查主线:先用 curl 直接打 SGLang 的 /v1/embeddings,分别带和不带 Authorization 发起请求,观察 401 是否变化。若不带 key 也 401,优先查 SGLang 启动参数/环境变量里的 api-key 配置;若带 key 仍 401,再查网关转发和 RAG 侧实际注入的请求头。边界:不同 SGLang 版本的鉴权参数名和校验行为会有差异,需结合当前部署确认。

先把 401 分层定位

SGLang 的 /v1/embeddings 接口通常走 OpenAI 兼容格式;RAG 服务通常把 embedding 请求发往这个接口。401 出现时,先从 RAG 进程的网络路径向外看,逐个确认请求经过了哪些层。常见路径是 RAG 进程 -> 网关/Ingress -> SGLang 服务。下面命令可用于直接访问 SGLang 服务,绕过网关;注意替换实际地址、模型名和 key。

curl -i http://127.0.0.1:30000/v1/embeddings -H "Authorization: Bearer your_key_here" -H "Content-Type: application/json" -d '{"model": "your-model-name", "input": ["hello"]}'

把 Authorization 整行去掉再执行一次。如果两条路径都 401,重点转向 SGLang 服务配置和网关策略;如果去掉 Authorization 后请求能返回 200,而 RAG 服务带着 key 仍 401,则问题在 RAG 侧请求头注入或网关对 Authorization 的改写。

核对 SGLang 的 API Key 开关

SGLang 服务是否要求 API Key,通常由启动参数或环境变量控制。启动命令里若看到 api-key 相关参数,说明请求必须带正确 key。有的部署通过环境变量传参,需要结合容器或进程管理方式确认。可以先用 ps 查看进程参数,再检查 compose、Kubernetes Deployment 或 systemd unit 中的 environment:

嵌入SGLang的RAG服务中调用embedding接口返回401的API Key校验逻辑排查
ps aux | grep sglang
# 在 Kubernetes 里用:
kubectl -n 你的命名空间 get deploy 你的服务名 -o yaml | grep -i api-key

如果启动参数里没有开启 api-key,但仍然 401,就要看 SGLang 前面的 ingress、istio、nginx 或云负载均衡是否做了额外校验;这类场景返回头往往不是 SGLang 的格式,或者响应里有 gateway 特征。

确认 RAG 服务实际发出去的请求头

另一个高发原因是 RAG 服务的 embedding client 配置了错误 header 或 key 为空。部分 OpenAI SDK 默认用 Authorization: Bearer,但有些业务代码会用 X-API-Key,而 SGLang 的 OpenAI 兼容接口通常校验 Authorization: Bearer,具体以部署为准。可以用脚本最小化验证:

嵌入SGLang的RAG服务中调用embedding接口返回401的API Key校验逻辑排查
import os, requests

endpoint = os.getenv("SGLANG_ENDPOINT", "http://127.0.0.1:30000/v1/embeddings")
resp = requests.post(
    endpoint,
    headers={"Authorization": "Bearer " + os.getenv("SGLANG_API_KEY", "")},
    json={"model": "your-model-name", "input": ["hello"]},
    timeout=10,
)
print(resp.status_code, resp.text)

这个脚本能同时回答三个问题:endpoint 是否可达、key 环境变量是否有值、header 格式是否正确。如果脚本成功而 RAG 服务里仍 401,再进入 RAG 代码的配置链路,确认传给 OpenAI SDK 的 base_url 和 api_key 是从哪份配置读出来的。

按清单收口,避免反复试错

按下面几条逐项确认,能覆盖大多数 401 场景:

  • 确认 401 响应体来自 SGLang 还是上游网关;不同来源需要查的配置完全不同。
  • 确认 SGLang 启动参数或环境变量里是否开启了 api-key;开启后 key 必须与 RAG 侧配置完全一致。
  • 打印 RAG 服务实际发出的 Authorization header,检查是否有空格、换行或在代理层被改写。
  • 确认 RAG 服务配置的 endpoint、模型名和 SGLang 实际发布的模型一致;模型名不一致虽然通常不是 401,但会影响后续报错判断。

一个需要留意的边界:某些网关或反向代理会先吞掉 Authorization 头,导致 SGLang 层收到请求后判断无 key,从而返回 401。这种情况在直连正常、走网关失败时最容易出现。处理时不要只改 key,先查转发规则里是否有 header 过滤、重写或白名单。