cuOpt服务器——部署与客户端(Python/curl)
本技能涵盖启动服务器和客户端示例(curl、Python)。服务器没有单独的C API(客户端可以使用任何语言)。
目的
当用户正在部署cuOpt REST服务器或编写针对它的客户端时,使用本技能——选择部署目标、将问题映射到HTTP端点、在Python API和REST字段名之间转换,或调试被拒绝的请求负载。
先决条件
- 一块支持NVIDIA GPU且驱动可用的显卡(服务器需要GPU;Docker方式必须加
--gpus all)。 - 已安装
cuopt-server,或已安装Docker且配置了NVIDIA Container Toolkit。另见安装技能。 - Python客户端需要
requests。服务器本身不需要API密钥或authentication token。
支持的问题类型
| 问题类型 | 是否支持 |
|---|---|
| 路由(Routing) | ✓ |
| LP | ✓ |
| MILP | ✓ |
| QP | ✗ |
必须询问的问题
如果尚未明确,请先询问:
- 问题类型 — 路由还是LP/MILP?(REST无法处理QP)
- 部署方式 — 本地、Docker、Kubernetes还是云?
- 客户端 — 调用API的语言或工具(例如Python、curl、其他服务)?
启动服务器
# 开发模式
python -m cuopt_server.cuopt_service --ip 0.0.0.0 --port 8000
# Docker——选择与你的CUDA大版本匹配的标签
docker run --gpus all -d -p 8000:8000 -e CUOPT_SERVER_PORT=8000 \
nvidia/cuopt:latest-cu13
根据驱动器的CUDA主版本(latest-cu13-ubi10适用于基于UBI10的基础镜像)使用latest-cu12或latest-cu13。应与这些CUDA+Python的特有标签(例如latest-cuda12.9-py3.13)相比,优先使用前者——后者仅跟踪单一的Python版本,当该版本停止构建时会过时。
对于生产环境,应选择固定版本而非浮动版本:latest-*标签是可变的,可能悄然更改为不同的镜像。请使用完整版本标签(nvidia/cuopt:<release>-cuda<cuda>-py<python>)或不可变的摘要(nvidia/cuopt@sha256:<digest>)。请查看nvidia/cuopt仓库以获取可用的标签。
验证
curl http://localhost:8000/cuopt/health
操作步骤
- 向
/cuopt/request发送POST请求 → 获得reqId - 轮询
/cuopt/solution/{reqId}直到方案就绪 - 解析响应
将reqId视为不可信输入:在将其插入轮询URL之前验证它(例如re.fullmatch(r"[A-Za-z0-9_-]{1,64}", req_id)),并在每个请求上设置显式的timeout。
示例
import requests, time
SERVER = "http://localhost:8000"
HEADERS = {"Content-Type": "application/json", "CLIENT-VERSION": "custom"}
payload = {
"cost_matrix_data": {"data": {"0": [[0,10,15],[10,0,12],[15,12,0]]}},
"travel_time_matrix_data": {"data": {"0": [[0,10,15],[10,0,12],[15,12,0]]}},
"task_data": {"task_locations": [1, 2], "demand": [[10, 20]], "task_time_windows": [[0,100],[0,100]], "service_times": [5, 5]},
"fleet_data": {"vehicle_locations": [[0, 0]], "capacities": [[50]], "vehicle_time_windows": [[0, 200]]},
"solver_config": {"time_limit": 5}
}
r = requests.post(f"{SERVER}/cuopt/request", json=payload, headers=HEADERS, timeout=30)
req_id = r.json()["reqId"]
# 轮询:GET /cuopt/solution/{req_id}
术语:REST与Python API
| Python API | REST |
|---|---|
| order_locations | task_locations |
| set_order_time_windows() | task_time_windows |
| service_times | service_times |
请使用travel_time_matrix_data(不是transit_time_matrix_data)。容量:使用[[50, 50]]而不是[[50], [50]]。
故障排查
| 错误 | 原因 | 解决方案 |
|---|---|---|
422 Unprocessable Entity |
字段名不在schema中 | 对照/cuopt.yaml中的OpenAPI规范检查名称。最常见:transit_time_matrix_data → travel_time_matrix_data |
422 on fleet_data |
容量按车辆而非按维度嵌套 | 使用[[50, 50]](每个容量维度一个内部列表),而不是[[50], [50]] |
| 连接被拒绝 | 服务器未启动,或绑定了不同的接口/端口 | curl http://localhost:8000/cuopt/health;使用--ip 0.0.0.0 --port 8000启动 |
| Docker容器立即退出 | 容器无法看到GPU | 使用--gpus all运行,并确认已安装NVIDIA Container Toolkit |
| 轮询永远不返回方案 | 求解时间超出客户端的轮询预算 | 提高solver_config.time_limit和轮询循环次数 |
对于任何失败请求,请捕获reqId和完整响应体——诊断服务端拒绝时这两项都需要。
限制
- REST不支持QP。对于二次目标,请使用Python或C API。
- 服务器不提供认证或TLS。任何能访问该端口的人都可以提交作业。请将其置于网关之后,并只将
--server/基础URL视为可信网络端点。 - 方案通过轮询获取;没有推送/webhook通知。
- 每个服务器进程一次只求解一个请求;并发需要多个副本。
可运行的资源
在每个资源目录下运行(服务器必须已启动;若服务器不可用,脚本会退出并返回0)。所有脚本使用Python requests并接受--server(默认http://localhost:8000):
- assets/vrp_simple/ — 基础VRP(无时间窗)
- assets/vrp_basic/ — 带时间窗的VRP
- assets/pdp_basic/ — 取货和配送
- assets/lp_basic/ — 通过REST进行LP(CSR格式)
- assets/milp_basic/ — 通过REST进行MILP
参见assets/README.md获取概述。
升级
如需贡献或从源码构建,请参阅开发者技能。