mortred_model_server

HTTP API 契约

| English | 中文 | |—|—|

机器可读契约是 docs/openapi.json(每个模型进程的 GET /openapi.json 也提供)。 本页是人读摘要。不要再复制已删除的 {req_id, code, msg, data} 信封或 img_data 字段——那些请求会返回 422

拓扑说明:mortred-gateway

生产流量统一经由 mortred-gateway(默认 :8080)。网关先按 catalog id 匹配 /v1/models/{id}/…,再按遗留 server_uri 精确匹配,转发到 仅监听环回地址的模型服务器。网关负责外部 Bearer Token 鉴权 (MORTRED_GATEWAY_AUTH_TOKENMORTRED_API_TOKEN),将上游不可达映射为 503、传输失败映射为 502;下文所有模型服务器状态码均原样透传。网关的 GET /healthz 为公开端点。GET /metrics 含环回在内一律需要 MORTRED_METRICS_TOKEN。网关拒绝在缺少独立 scrape Bearer(不得与推理 token 相同)时启动。模型端口仅绑定环回地址、不得对外暴露。Mortred 自身是 明文 HTTP;对外服务必须由主机网络上的 Nginx 终结 TLS (mortredctl init-edge)。fail-closed 拒绝无鉴权监听、缺少 metrics token、 以及未设 MORTRED_EXPOSE=dockerunsafe 的通配绑定。

监督器(supervisor,:8787)在 /api/v1/ 下提供管理 REST API (health/catalog/status/生命周期/日志/metrics)与内嵌 Web UI; mortredctl 是它的命令行客户端。推理冒烟(控制台发送按钮和 mortredctl infer)把数据面信封 POST 到网关的 /v1/models/{id}/infer,Bearer 与管理 API 相同(MORTRED_API_TOKEN)。 监督进程只做管理(catalog / 启停 / 日志 / UI)。推理和异步 jobs 走网关。:8080 上的遗留 {server_uri} 仍然可用。

状态码、端点或响应结构变更必须同时更新 docs/openapi.json (用 python scripts/gen_openapi.py 重新生成)。

鉴权

当服务器配置了 auth_token 时,模型推理端点要求携带 Authorization 请求头:

Authorization: Bearer <token>

请求规则

通用响应封装

{
  "status": 0,
  "status_str": "OK",
  "task_id": "客户端提供或服务器生成",
  "model": { "name": "MOBILENETV2", "version": "" },
  "results": [
    {
      "status": 0,
      "data": {
        "class_id": 123,
        "category": "tabby cat",
        "scores": [0.1, 0.8, 0.1]
      }
    }
  ],
  "server_time_ms": 41.2,
  "partial": false
}

契约校验失败时(HTTP 422):

{
  "status": 66,
  "status_str": "invalid request parameter",
  "task_id": "",
  "results": [],
  "server_time_ms": 0.0,
  "partial": false,
  "errors": [
    {
      "pointer": "/img_data",
      "message": "field 'img_data' was removed; use images: [\"<base64>\"] (migration: img_data -> images[0])"
    }
  ]
}

先看 HTTP 状态,再看顶层 status,再逐项看 results[i].status。该项失败时 results[i].datanull。忽略未知响应字段。各任务载荷在 results[].data 下,定义见 docs/openapi.json components.schemassrc/server/response_serializers.h)。

HTTP 状态码映射

JSON 字段名是 status(不是 code)。映射见 src/server/http_status.h

status 含义 HTTP
0 成功 200
68 截止超时,部分结果 200
50 JSON 解析错误 400
3 输入图片为空 400
66 非法请求(img_data、未知键、错误 params 422
60 不支持的媒体类型 415
61 请求实体过大 413
67 单请求条目过多 413
62 方法不允许 405
63 未找到 404
65 服务未就绪 503
4 模型运行超时 504
6 模型输出契约失败 500
401 未授权 401
429 限流或等待队列已满(携带 Retry-After 429
其他 服务器错误 500

通用响应头

Content-Type: application/json; charset=utf-8
X-Request-ID: <task_id>
Cache-Control: no-store

通用端点

端点 方法 说明
/healthz GET 存活探针
/ready GET 就绪探针
/metrics GET Prometheus 指标(鉴权见上)
/openapi.json GET OpenAPI 文档(内嵌副本)

未知路径(含已删除的 /welcome/hello_world HTML 探活)返回 404 与 进程级 UnifiedResponse

模型推理请求

{
  "req_id": "可选",
  "images": ["base64 编码的图片"],
  "params": {},
  "options": {}
}

images 必填且恒为数组(≥1)。params / options 为可选对象。阈值、 DDPM timesteps 等模型参数放在 params 里,不要放在根上。生成式模型同样 需要 images[];像素会被忽略,dummy base64 即可。

已删除字段:img_data(HTTP 422)

下面不是成功请求。即使同时带了 images 也会被拒绝:

{
  "req_id": "legacy",
  "img_data": "base64 编码的图片"
}

过载行为

max_queue_depth > 0 且等待队列已满时,模型服务器立即以 429 拒绝,并携带 Retry-After 响应头(依据队列深度、运行时长 EWMA 与 worker 数量估算排水时间,钳制在 1-60 秒)。网关将两者原样转发。

新增可选服务端配置键:max_queue_depth(0 = 不限制)、max_batch_size (默认 1;大于 1 时在 max_batch_delay_ms 窗口内凑批),以及 mortred_queue_rejected_total / mortred_batch_size / mortred_batch_window_wait_ms 指标。

批内逐条失败隔离:一条失败(坏图、解码错误)只返回它自己的错误 status, 同批其他条目照常得到结果;仅会话级失败(引擎错误)才会使全部参与 条目失败。

异步任务

服务端开启 async_enabled 后,长耗时推理可异步提交。模型端口上的路径不变 (POST /jobsGET /jobs/{id} 等)。经 网关 时同一套处理带 catalog id 前缀;网关无状态,并把 Location / poll_url / result_url 改写成该前缀:

网关 方法 模型端口上游
/v1/models/{id}/infer POST {server_uri}
/v1/models/{id}/jobs POST /jobs
/v1/models/{id}/jobs/{job} GET /jobs/{job}
/v1/models/{id}/jobs/{job}/wait GET /jobs/{job}/wait + query
/v1/models/{id}/jobs/{job}/result GET /jobs/{job}/result
{server_uri} POST {server_uri}(遗留)

GET /v1/models/{id}/inferGET {server_uri} 返回 405。未知 {id} 与未知 server_uri 使用同一 404 信封。模型未开异步时,上游 404 原样透传。

端点(模型端口) 成功 错误
POST /jobs 准入时 202,返回 job_idstate: pendingpoll_urlresult_url 准入队列满时 429
GET /jobs/{id} 200,返回 statepending/running/done/failed/timeout 未知 id 404
GET /jobs/{id}/wait?timeout=N job 进入终态或 wait 预算耗尽时 200timeout 单位毫秒;默认 30000,上限 300000)。预算耗尽时 state 仍可能是 pending/running 未知 id 404
GET /jobs/{id}/result 200 标准响应封装(可重复读取) 未知 id 404,未完成 409(含 pending/running/failed/timeout

202 表示服务器接受了该 job,不表示推理已经完成。正确的客户端不要把 POST /jobs 当成阻塞的 /infer。提交体与 /infer 相同(images[])。 逐步验收步骤见 async-jobs-customer-test.zh-cn.md

任务账本保存在内存中(重启即失)。组件设计、并发契约与验证门禁见 async-job-table.zh-cn.md