帮你快速理解、总结文档立即下载

部署在线推理服务(REST API)

最近更新时间:2026-11-06 15:28:01
我的收藏
将已注册的模型部署为对外可调用的 REST API,是模型服务模块最核心的操作。本文介绍通过控制台部署、通过 MLflow Deployments SDK 部署、获取调用地址与鉴权 Token 的完整流程。

前提条件

已在 Catalog 中注册并发布模型,且模型版本处于可发布状态。详见 模型管理。
当前账号在工作空间内具备模型服务的创建权限。
如使用 SDK 部署:已安装 mlflow 与 DataBuddy 提供的部署插件 wedata3-mlflow-tcdeploy-plugin。

方式一:通过控制台部署

操作步骤

1. 进入创建页:在 Catalog 模型详情页单击 部署模型 ;或进入 数据科学 > 模型服务 ,单击 创建服务 。
2. 填写基本配置:输入 服务名称 (创建后不可修改,工作空间内唯一),可选填 服务描述 (不超过 100 字)。
3. 配置服务版本实例:
部署模型、版本 :选择 Catalog 中的模型及其版本。多个版本实例须保持输入、输出参数一致,否则服务调用失败。
资源来源、资源规格 :选择「平台按量计费资源」,并选择单副本的资源规格(GPU 模型选 GPU 规格)。
请求限流 :不限流(最大 500 QPS)、单实例 QPS 或单实例最大并发。
副本数量 :填写目标副本数量(多副本可提升可用性)。 单击 + 新增服务版本实例 可追加版本,用于灰度发布或 A/B 测试。
1. 设置高级配置:
是否生成鉴权 :开启后服务调用需进行签名认证,可在服务调用页面查看签名密钥及签名计算指引。
服务日志投递 :开启后服务日志持久化存储至日志服务(默认存储 15 天),需提前开通日志服务并创建日志集与日志主题。详见 推理监控与日志。
1. 保存并启动:校验必填项后拉起计算资源并加载模型,状态依次进入「未就绪 → 启动中 → 运行中」;也可先保存草稿,稍后在详情页启动。
2. 获取调用地址:服务进入运行中后,进入 服务详情页 复制服务 API 地址,并在 服务调用 页面查看签名密钥与调用示例。
说明:
生产服务建议开启 鉴权 与 服务日志投递 :前者保证调用安全,后者便于在线问题排查。资源规格与副本数量详见 资源配置与自动伸缩。

方式二:通过 MLflow Deployments SDK 部署

SDK 以 DataBuddy 提供的部署插件 wedata3-mlflow-tcdeploy-plugin 形式接入 MLflow 官方的 Deployments API(target 为 tcdeploy)。
注意:
该插件仅支持远程部署,不支持 mlflow deployments run-local 本地运行;调用本地运行会抛 NotImplementedError,请改用 client.create_deployment(...)。

安装与环境准备

%pip install "wedata3-mlflow-tcdeploy-plugin"
SDK 运行所需的临时密钥与工作空间上下文,由 DataBuddy Notebook 内核或调度运行时自动注入,在平台内运行无需手动配置 。仅当在本地 IDE 调试时,才需自行配置临时密钥、工作空间 ID、地域等环境变量;缺少必需配置时,初始化会抛 ValueError 并提示缺失项。

初始化客户端

import mlflow_tcdeploy_plugin; print(mlflow_tcdeploy_plugin.__version__) # 应为 0.1.1
from mlflow.deployments import get_deploy_client

# 推荐统一通过官方 API 获取客户端,target 固定为 "tcdeploy"
client = get_deploy_client("tcdeploy")

模型 URI 规范

create_deployment / update_deployment 的 model_uri 必须使用 MLflow 三段式 Models URI:
models:/<catalog_name>.<schema_name>.<model_name>/<version>
协议必须为 models:/,否则抛 ValueError;
模型名必须是三段式 Catalog.Schema.Model,缺失任一段抛 ValueError;
版本号不可为空;
不支持 runs:/<run_id>/model 形式,请先将模型注册到 Catalog(详见 模型管理)。

创建服务

resp = client.create_deployment(
name="churn-model-svc", # 服务名称(ServiceName)
model_uri="models:/<catalog_name>.<schema_name>.<model_name>/<version>",
config={
"instance_type": "<instance_spec>", # 必填:实例规格名,用 list_instance_types() 查询
"replicas": 2, # 副本数,默认 1
"charge_type": "POSTPAID_BY_HOUR", # 计费模式,默认按量计费,可选 PREPAID
"scale_mode": "MANUAL", # 弹性模式,默认 MANUAL,可选 AUTO
"authorization_enable": True, # 是否开启鉴权 Token,生产建议开启
"log_enable": True, # 是否开启日志投递,生产建议开启
"service_description": "用户流失预测在线服务",
},
)
service_id = resp["data"]["service_id"] # 形如 ms-xxxxxx
service_group_id = resp["data"]["service_group_id"] # 形如 msg-xxxxxx
注意:
创建服务的几条关键约定:
1. config 必须包含 instance_type,否则在请求发出前就会被拦下抛 ValueError。可用规格通过 list_instance_types() 查询,或在控制台「创建服务」页面查看。
2. name 是服务名称(ServiceName) ;返回的 service_id(ms-xxxxxx)才是后续 update_deployment / delete_deployment / get_deployment 的入参,service_group_id(msg-xxxxxx)用于 predict。请务必把这两个 ID 落库或写进 Notebook 输出。
3. endpoint 参数语义是服务组 ID(ServiceGroupId) :传入已有服务组可将新服务加入该组实现灰度;首次创建时不传。
4. 未在文档中列出的 config 字段会原样下发,拼错的 key 不会报错而是静默失效,建议把配置抽成常量集中维护。
常用 config 字段速查:
字段
说明
instance_type(必填)
实例规格名
replicas
副本数,默认 1
charge_type
计费模式,默认 POSTPAID_BY_HOUR,可选 PREPAID
scale_mode
弹性模式,默认 MANUAL,可选 AUTO
scheduled_action
定时扩缩容配置
service_limit
服务级限流(QPS / 带宽等)
authorization_enable
是否开启鉴权 Token,默认 False
log_enable
是否开启日志投递,默认 False
service_description
服务业务描述
inference_table_push_enable
是否开启推理表写入
catalog_path / schema_path / payload_path
推理表所在 Catalog / Schema 与 Payload 路径

查询实例规格

# 查询可用规格;spec_type 可选 "CPU" / "GPU",不传则全部
cpu = client.list_instance_types(spec_type="CPU")
print(len(cpu), cpu[:2])
print(client.list_instance_types(spec_type="GPU")[:2])
print(client.get_instance_type_prices([s["spec_name"] for s in cpu if s["available"]][:2]))
返回项中的 spec_name 即 config["instance_type"] 的取值。

等待服务就绪

create_deployment 返回时服务通常仍处于部署中状态,副本拉起、模型加载、健康检查一般需要 1~5 分钟。线上联调或自动化场景必须显式轮询 get_deployment 直到进入终态:
import time

TERMINAL = {"RUNNING", "FAILED", "STOPPED"}
deadline = time.time() + 600 # 10 分钟超时上限,避免长时间阻塞

while True:
detail = client.get_deployment(service_id)
status = detail["data"].get("status")
print("status =", status)
if status in TERMINAL:
break
if time.time() > deadline:
raise TimeoutError(f"service {service_id} not ready, status={status}")
time.sleep(15) # 轮询间隔 ≥ 10 秒,避免触发频率限制

发起在线推理

result = client.predict(
deployment_name=service_group_id, # 注意:是 service_group_id,不是 service_id
inputs={"dataframe_records": [{"f1": 1.0, "f2": 2.0}]},
config={"auth_token": "Bearer <token>"}, # 服务开启鉴权时必填
)
print(result)
注意:
inputs 必须是 JSON 可序列化的对象(dict / list / 基础类型)。numpy.ndarray、pandas.DataFrame、datetime 等需先转换(如 df.to_dict(orient="records")),否则抛 ValueError。
endpoint 参数为目标推理实例的 HTTP 相对路径,默认 /predict;只能传相对路径(如 /v1/models/x:predict),传入绝对 URL、协议相对地址、含 @ 或 .. 路径穿越的值都会抛 ValueError。
推理服务返回合法 JSON 时得到解析后的 dict / list;返回非 JSON 文本时包装为 {"raw": "<原始文本>"},业务代码应先判断 "raw" in result 再决定如何解析。

更新、扩缩容与版本切换

update_deployment 为部分更新(PATCH)语义:只发送本次显式提供的字段,未提供的字段保持服务端原值。name 入参为 service_id。
# 1) 调整副本数(普通更新,不重建服务)
client.update_deployment(name=service_id, config={"replicas": 4})

# 2) 切换到新模型版本(自动滚动重启,无需先下线)
client.update_deployment(
name=service_id,
model_uri="models:/<catalog_name>.<schema_name>.<model_name>/<new_version>",
)

# 3) 停止 / 恢复 / 触发扩缩容(service_action 特殊语义)
client.update_deployment(name=service_id, config={"service_action": "STOP"})
client.update_deployment(name=service_id, config={"service_action": "RESUME"})
client.update_deployment(name=service_id, config={"service_action": "SCALE"})
注意:
service_action(STOP / RESUME / SCALE)是排他字段:一旦 config 中包含 service_action,本次请求中的其它字段(包括 model_uri、replicas)都会被忽略。切版本、扩缩容与停止、恢复请拆成独立的调用。回滚只需再次 update_deployment(model_uri=旧版本),无需特殊接口。
灰度发布:若对版本切换的原子性要求很高,可用同一个 service_group_id 再创建一个新服务(create_deployment(..., endpoint=service_group_id)),验证通过后停止并删除旧服务。流量比例的精细切分在控制台完成,SDK 聚焦于部署生命周期本身。

查询与下线服务

# 列举当前工作空间下的服务组;传 endpoint 可按 ServiceGroupId 过滤
groups = client.list_deployments()
for g in groups:
print(g["name"], g.get("service_group_name"), g.get("service_group_status"))

# 删除服务(幂等:服务不存在时不会报错)
client.delete_deployment(service_id)
说明:
list_deployments 返回项的 name 字段即为 service_group_id(MLflow Deployments 规范要求)。删除为不可逆操作,建议先 update_deployment(name=service_id, config={"service_action": "STOP"}) 冷却,让在途请求自然结束后再删除。

错误处理

SDK 不返回错误码字段,所有错误通过 Python 异常传递:
异常类型
触发场景
处理建议
ValueError
入参 / 环境变量校验失败(缺 instance_type、model_uri 非三段式、inputs 不可序列化、endpoint 非法等)
按错误信息修正参数或环境变量
mlflow.exceptions.MlflowException
平台接口调用失败,message 形如 <Code>: <Message>
解析前缀 Code(如 UnauthorizedOperation 权限不足、ResourceNotFound ID 错误、LimitExceeded 配额超限、RequestLimitExceeded 频率超限)后排查
NotImplementedError
调用了本地运行 run_local
改用 client.create_deployment(...) 远程部署

服务管理

进入 数据科学 > 模型服务 可查看服务列表并对服务进行启动、停止、编辑、新增版本、删除等操作。
服务管理分两级页面:单击服务名称进入 服务详情页 (管理版本与流量),再单击版本 ID 进入 版本详情页 (管理实例与运行)。

服务详情页

单击服务名称进入。顶部操作区:权限 、流量分配 、服务调用 、+ 新增版本 、Buddy 。
主区为 服务版本 列表,列含 ID、服务名称、服务版本、状态、流量比、操作(编辑、监控、更多);下方页签为 调用监控 、服务鉴权 。
右侧信息面板:
面板
内容
基本信息
描述、创建人、上次修改时间。
高级配置
日志服务配置、推理表、服务鉴权的启用状态。可单击 编辑配置 二次开启 / 关闭。

版本详情页

在服务详情页单击版本 ID 进入。标题右侧显示版本状态徽标(如「运行中」);顶部操作区:刷新 、停止 、编辑 、删除 、Buddy 。
主区为 实例列表 ,展示各副本实例(实例名称、实例 id、实例状态、创建时间、操作);单击操作列 更多 可对实例 重建 或 进入容器 。下方页签为 监控 、事件 、日志 。
右侧信息面板:
面板
内容
基本信息
描述、服务 ID、状态。
接入配置
接入模型及版本、副本数量、请求限流。可单击 编辑配置 调整。
付费方式
计费方式(平台按量计费资源)、算力规格(所选 CPU / GPU 规格)。
常用运维操作:
操作
说明
新增版本
单次新增 1 个服务版本,用于灰度或 A/B。
编辑配置
二次开启 / 关闭日志服务、推理表、鉴权,或调整接入配置。
停止
释放底层计算资源并停止计费,需要时可重新启动。
删除
永久删除服务及其所有版本。删除前请确认无业务调用方仍在使用。
调用监控、监控、日志、事件的具体指标与字段详见 推理监控与日志。
警告:
删除服务为不可恢复 操作。删除后服务地址立即失效,所有副本释放;如该服务已开启推理表,历史推理数据仍保留在 Catalog 中。

常见问题

Q:服务长时间停留在「未就绪」状态怎么办? A:进入版本详情页查看 事件 与 日志 页签,常见原因包括:模型服务包拉取失败、资源池容量不足、模型加载报错。可结合日志服务定位具体错误。
Q:如何在不影响线上流量的情况下发布新版本? A:先在原服务下「新增版本」,初始流量比设为 0%;版本进入运行中后,通过编辑流量比逐步切分(如 90/10 → 50/50 → 0/100),实现灰度发布。

相关文档