全部产品
Search
文档中心

人工智能平台 PAI:Triton Inference Server镜像部署

更新时间:Jan 19, 2026

Triton Inference Server 是由 NVIDIA 开发的一款适用于深度学习与机器学习模型的推理服务引擎,支持将TensorRT、TensorFlow、PyTorch或ONNX等多种AI框架的模型部署为在线推理服务,并支持多模型管理、自定义backend等功能。本文介绍如何在PAI-EAS上部署基于 Triton 的推理服务。

前提条件

  • 与 PAI 同地域的对象存储 OSS Bucket。

  • 已训练好的模型文件(如 .pt.onnx.plan.savedmodel)。

快速入门:部署单模型服务

步骤一:准备模型仓库

Triton 要求在对象存储 OSS Bucket 中使用特定的目录结构。请按以下格式创建目录。具体操作请参见管理目录上传文件

oss://your-bucket/models/triton/
└── your_model_name/
    ├── 1/                    # 版本目录(必须为数字)
    │   └── model.pt          # 模型文件
    └── config.pbtxt          # 模型配置文件

关键要求:

  • 版本目录必须使用数字命名(123 等)。

  • 数字越大表示版本越新。

  • 每个模型都需要一个 config.pbtxt 配置文件。

步骤二:创建模型配置文件

创建 config.pbtxt 文件,配置模型的基础信息,示例如下:

name: "your_model_name"
platform: "pytorch_libtorch"
max_batch_size: 128

input [
  {
    name: "INPUT__0"
    data_type: TYPE_FP32
    dims: [ 3, -1, -1 ]
  }
]

output [
  {
    name: "OUTPUT__0"
    data_type: TYPE_FP32
    dims: [ 1000 ]
  }
]


# 使用GPU推理
# instance_group [
#   { 
#     kind: KIND_GPU
#   }
# ]

# 模型版本配置
# 仅加载最新版本(默认行为)
# version_policy: { latest: { num_versions: 1 }}

# 加载所有版本
# version_policy: { all { }}

# 加载最新的两个版本
# version_policy: { latest: { num_versions: 2 }}

# 加载指定版本
# version_policy: { specific: { versions: [1, 3] }}

配置参数说明

参数

是否必选

说明

name

模型名称。如指定,必须与模型目录名一致。

platform

模型框架。可选值:pytorch_libtorchtensorflow_savedmodeltensorflow_graphdeftensorrt_planonnxruntime_onnx

backend

platform 的替代配置。使用 python 可自定义推理逻辑。

max_batch_size

最大批处理大小。设为 0 表示禁用批处理。

input

输入张量配置:name(名称)、data_type(数据类型)、dims(维度)。

output

输出张量配置:name(名称)、data_type(数据类型)、dims(维度)。

instance_group

指定推理设备:KIND_GPU 或 KIND_CPU(配置示例见前文config.pbtxt文件)。

version_policy

控制加载哪些模型版本(配置示例见前文config.pbtxt文件)。

重要

platform 和 backend 至少配置一项。

步骤三:部署服务

  1. 登录PAI控制台,在页面上方选择目标地域。

  2. 在左侧导航栏单击模型在线服务(EAS),选择目标工作空间,然后单击部署服务

  3. 场景化模型部署区域,单击Triton部署

  4. 配置部署参数:

    • 服务名称:自定义配置服务名称。

    • 模型配置:配置类型选择对象存储(OSS),填写模型仓库路径(如 oss://your-bucket/models/triton/)。

    • 实例数资源规格按需选择。估算模型部署所需显存您可参考估算大模型所需显存

  5. 单击部署,等待服务启动完成。

步骤四:启用gRPC(可选)

默认情况下,Triton 在端口 8000 提供 HTTP 服务。如需使用 gRPC:

  1. 单击服务配置页面右上角的切换为自定义部署

  2. 环境信息区域,将端口号修改为 8001

  3. 服务功能 > 高级网络下,启用gRPC

  4. 单击部署

模型部署成功后即可调用服务

部署多模型服务

如需在单个 Triton 实例中部署多个模型,只需将多个模型放在同一仓库目录下:

oss://your-bucket/models/triton/
├── resnet50_pytorch/
│   ├── 1/
│   │   └── model.pt
│   └── config.pbtxt
├── densenet_onnx/
│   ├── 1/
│   │   └── model.onnx
│   └── config.pbtxt
└── classifier_tensorflow/
    ├── 1/
    │   └── model.savedmodel/
    │       ├── saved_model.pb
    │       └── variables/
    └── config.pbtxt

部署步骤与单模型相同。Triton 会自动加载仓库中的所有模型。

使用Python Backend自定义推理逻辑

当您需要自定义预处理、后处理或推理逻辑时,可以使用 Triton 的 Python Backend。

目录结构

your_model_name/
├── 1/
│   ├── model.pt          # 模型文件
│   └── model.py          # 自定义推理逻辑
└── config.pbtxt

实现Python Backend

创建 model.py 文件,定义 TritonPythonModel 类:

import json
import os
import torch
from torch.utils.dlpack import from_dlpack, to_dlpack

import triton_python_backend_utils as pb_utils


class TritonPythonModel:
    """必须以 "TritonPythonModel" 为类名"""

    def initialize(self, args):
        """
        初始化函数,可选实现,在加载模型时被调用一次,可用于初始化与模型属性、模型配置相关的信息。
        Parameters
        ----------
        args : 字典类型,其中keys和values都为string 类型,具体包括:
          * model_config:JSON格式模型配置信息。
          * model_instance_kind:设备型号。
          * model_instance_device_id:设备ID。
          * model_repository:模型仓库路径。
          * model_version:模型版本。
          * model_name:模型名。
        """

        # 将JSON字符串类型的模型配置内容转为Python的字典类型。
        self.model_config = model_config = json.loads(args["model_config"])

        # 获取模型配置文件中的属性。
        output_config = pb_utils.get_output_config_by_name(model_config, "OUTPUT__0")

        # 将Triton types转为numpy types。
        self.output_dtype = pb_utils.triton_string_to_numpy(output_config["data_type"])

        # 获取模型仓库的路径。
        self.model_directory = os.path.dirname(os.path.realpath(__file__))

        # 获取模型推理使用的设备,本例中使用GPU。
        self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
        print("device: ", self.device)

        model_path = os.path.join(self.model_directory, "model.pt")
        if not os.path.exists(model_path):
            raise pb_utils.TritonModelException("Cannot find the pytorch model")
        # 通过.to(self.device)将pytorch模型加载到GPU上。
        self.model = torch.jit.load(model_path).to(self.device)

        print("Initialized...")

    def execute(self, requests):
        """
        模型执行函数,必须实现;每次请求推理都会调用该函数,若设置了 batch 参数,还需由用户自行实现批处理功能
        Parameters
        ----------
        requests : pb_utils.InferenceRequest类型的请求列表。

        Returns
        -------
        pb_utils.InferenceResponse 类型的返回列表。列表长度必须与请求列表一致。
        """

        output_dtype = self.output_dtype

        responses = []

        # 遍历request列表,并为每个请求都创建对应的response。
        for request in requests:
            # 获取输入tensor。
            input_tensor = pb_utils.get_input_tensor_by_name(request, "INPUT__0")
            # 将Triton tensor转换为Torch tensor。
            pytorch_tensor = from_dlpack(input_tensor.to_dlpack())

            if pytorch_tensor.shape[2] > 1000 or pytorch_tensor.shape[3] > 1000:
                responses.append(
                    pb_utils.InferenceResponse(
                        output_tensors=[],
                        error=pb_utils.TritonError(
                            "Image shape should not be larger than 1000"
                        ),
                    )
                )
                continue

            # 在GPU上进行推理计算。
            prediction = self.model(pytorch_tensor.to(self.device))

            # 将Torch output tensor转换为Triton tensor。
            out_tensor = pb_utils.Tensor.from_dlpack("OUTPUT__0", to_dlpack(prediction))

            inference_response = pb_utils.InferenceResponse(output_tensors=[out_tensor])
            responses.append(inference_response)

        return responses

    def finalize(self):
        """
        模型卸载时调用,可选实现,可用于模型清理工作。
        """
        print("Cleaning up...")
重要

当使用Python Backend时,Triton的某些行为会发生改变,请务必注意:

  • max_batch_size 失效config.pbtxt中的max_batch_size参数对Python Backend的动态批处理无效。您必须在execute方法中自行遍历requests列表,手动拼接Batch进行推理。

  • instance_group 失效config.pbtxt中的instance_group无法控制Python Backend使用CPU或GPU。您必须在initializeexecute方法中,通过代码(如 pytorch_tensor.to(torch.device("cuda")))显式地将模型和数据移动到目标设备。

更新配置文件

name: "resnet50_pt"
backend: "python"
max_batch_size: 128
input [
  {
    name: "INPUT__0"
    data_type: TYPE_FP32
    dims: [ 3, -1, -1 ]
  }
]
output [
  {
    name: "OUTPUT__0"
    data_type: TYPE_FP32
    dims: [ 1000 ]
  }
]

parameters: {
    key: "FORCE_CPU_ONLY_INPUT_TENSORS"
    value: {string_value: "no"}
}

其中关键参数说明如下:

  • backend:需指定为python。

  • parameters:可选配置,当模型推理使用GPU时,可将FORCE_CPU_ONLY_INPUT_TENSORS参数设置为no,来避免推理计算时输入Tensor在CPU与GPU之间来回拷贝产生不必要的开销。

部署服务

使用Python backend必须设置共享内存。在自定义模型部署 > JSON独立部署填写如下JSON配置并部署,即可实现自定义模型推理逻辑。

{
  "metadata": {
    "name": "triton_server_test",
    "instance": 1
  },
  "cloud": {
        "computing": {
            "instance_type": "ml.gu7i.c8m30.1-gu30",
            "instances": null
        }
    },
  "containers": [
    {
      "command": "tritonserver --model-repository=/models",
      "image": "eas-registry-vpc.<region>.cr.aliyuncs.com/pai-eas/tritonserver:25.03-py3",
      "port": 8000,
      "prepare": {
        "pythonRequirements": [
          "torch==2.0.1"
        ]
      }
    }
  ],
  "storage": [
    {
      "mount_path": "/models",
      "oss": {
        "path": "oss://oss-test/models/triton_backend/"
      }
    },
    {
      "empty_dir": {
        "medium": "memory",
        // 配置共享内存为1 GB。
        "size_limit": 1
      },
      "mount_path": "/dev/shm"
    }
  ]
}

关键JSON配置说明

  • containers[0].image: Triton官方镜像。请将 cn-hangzhou 替换为您服务所在的地域。

  • containers[0].prepare.pythonRequirements: 在此列出您的Python依赖库,EAS会在服务启动前自动安装。

  • storage: 包含两个挂载项。

    • 第一个将您的OSS模型仓库路径挂载到容器的 /models 目录。

    • 第二个是必须配置的共享内存。Triton Server与Python Backend进程之间通过共享内存 /dev/shm 传递张量数据以实现零拷贝,从而最大化性能。size_limit 单位为GB,请根据模型和并发量估算所需大小。

调用服务

获取服务端点和Token

  1. 进入模型在线服务(EAS)页面,单击服务名称。

  2. 服务详情页签,单击查看调用信息,复制公网调用地址Token

发送HTTP请求

端口号配置为8000时,服务支持发送HTTP请求。

import numpy as np
# 安装tritonclient包请执行命令:pip install tritonclient
import tritonclient.http as httpclient

# 服务部署后生成访问地址(服务端点),不带http://
url = '1859257******.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/triton_server_test'

triton_client = httpclient.InferenceServerClient(url=url)

image = np.ones((1,3,224,224))
image = image.astype(np.float32)

inputs = []
inputs.append(httpclient.InferInput('INPUT__0', image.shape, "FP32"))
inputs[0].set_data_from_numpy(image, binary_data=False)
outputs = []
outputs.append(httpclient.InferRequestedOutput('OUTPUT__0', binary_data=False))  # 获取 1000 维的向量

# 指定模型名称、请求Token、输入输出。
results = triton_client.infer(
    model_name="<your-model-name>",
    model_version="<version-num>",
    inputs=inputs,
    outputs=outputs,
    headers={"Authorization": "<your-service-token>"},
)
output_data0 = results.as_numpy('OUTPUT__0')
print(output_data0.shape)
print(output_data0)

发送gRPC请求

端口号配置为8001,并添加gRPC相关配置后,服务支持发送gRPC请求。

重要

注意:gRPC的访问地址和HTTP的不相同,请重新从服务详情页面获取。

#!/usr/bin/env python
import grpc
# 安装tritonclient包请执行命令:pip install tritonclient
from tritonclient.grpc import service_pb2, service_pb2_grpc
import numpy as np

if __name__ == "__main__":
    # 服务部署后生成访问地址(服务端点),不带http://,末尾添加“:80”
    host = (
        "service_name.115770327099****.cn-beijing.pai-eas.aliyuncs.com:80"
    )
    # 服务Token,实际应用中应使用真实的Token。
    token = "<your-service-token>"
    # 模型名称和版本。
    model_name = "<your-model-name>"
    model_version = "<version-num>"
    
    # 创建gRPC元数据,用于Token验证。
    metadata = (("authorization", token),)

    # 创建gRPC通道和存根,用于与服务器通信。
    channel = grpc.insecure_channel(host)
    grpc_stub = service_pb2_grpc.GRPCInferenceServiceStub(channel)
    # 构建推理请求。
    request = service_pb2.ModelInferRequest()
    request.model_name = model_name
    request.model_version = model_version

    # 构造输入张量,对应模型配置文件中定义的输入参数。
    input = service_pb2.ModelInferRequest().InferInputTensor()
    input.name = "INPUT__0"
    input.datatype = "FP32"
    input.shape.extend([1, 3, 224, 224])
    # 构造输出张量,对应模型配置文件中定义的输出参数。
    output = service_pb2.ModelInferRequest().InferRequestedOutputTensor()
    output.name = "OUTPUT__0"

    # 创建输入请求。
    request.inputs.extend([input])
    request.outputs.extend([output])
    # 构造随机数组并序列化为字节序列,作为输入数据。
    request.raw_input_contents.append(np.random.rand(1, 3, 224, 224).astype(np.float32).tobytes()) #数值类型
            
    # 发起推理请求,并接收响应。
    response, _ = grpc_stub.ModelInfer.with_call(request, metadata=metadata)
    
    # 提取响应中的输出张量。
    output_contents = response.raw_output_contents[0]  # 假设只有一个输出张量。
    output_shape = [1, 1000]  # 假设输出张量的形状是[1, 1000]。
    
    # 将输出字节转换为numpy数组。
    output_array = np.frombuffer(output_contents, dtype=np.float32)
    output_array = output_array.reshape(output_shape)
    
    # 打印模型的输出结果。
    print("Model output:\n", output_array)

调试技巧

启用详细日志

设置 verbose=True 可打印请求和响应的 JSON 数据:

client = httpclient.InferenceServerClient(url=url, verbose=True)

输出示例:

POST /api/predict/triton_test/v2/models/resnet50_pt/versions/1/infer, headers {'Authorization': '************1ZDY3OTEzNA=='}
b'{"inputs":[{"name":"INPUT__0","shape":[1,3,32,32],"datatype":"FP32","data":[1.0,1.0,1.0,.....,1.0]}],"outputs":[{"name":"OUTPUT__0","parameters":{"binary_data":false}}]}'

在线调试

可以直接在控制台的在线调试功能中进行测试,请求地址补全为/api/predict/triton_test/v2/models/resnet50_pt/versions/1/infer,Body使用详细日志中的 JSON 请求数据。

image

压测服务

以单个数据压测为例,操作步骤如下,更多压测说明请参见通用场景服务压测

  1. 压测任务页签,单击添加压测任务,选择已部署的Triton服务,并填写压测地址。

  2. 数据来源选择单个数据,并参考如下代码将JSON请求体转换为Base64编码的字符串。

    import base64
    
    # 已有的 JSON 请求体字符串
    json_str = '{"inputs":[{"name":"INPUT__0","shape":[1,3,32,32],"datatype":"FP32","data":[1.0,1.0,.....,1.0]}]}'
    # 直接编码
    base64_str = base64.b64encode(json_str.encode('utf-8')).decode('ascii')
    print(base64_str)

    image

常见问题

Q:出现报错:CUDA error: no kernel image is available for execution on the device,怎么办?

出现该报错的原因是镜像版本与GPU的兼容性问题,您可以尝试更换其他GPU型号的规格,如:A10、T4。

Q:使用HTTP调用报错:tritonclient.utils.InferenceServerException: url should not include the scheme,怎么解决?

出现该报错的原因是服务的url填写错误。获取服务端点的格式为:http://17519301*******.cn-hangzhou.pai-eas.aliyuncs.com/api/predict/wen*****注意,其与gRPC的访问地址不同),请去掉开头的http://

Q:使用gRPC调用报错:DNS resolution failed for wenyu****.175193***43.cn-hangzhou.pai-eas.aliyuncs.com/:80,怎么解决?

出现该报错的原因是服务的host填写错误。获取服务端点的格式为:http://we*****.1751930*****.cn-hangzhou.pai-eas.aliyuncs.com/注意,其与HTTP的访问地址不同),请去掉开头的http:// 以及末尾的/,然后在末尾补:80,最终变成:we*****.1751930*****.cn-hangzhou.pai-eas.aliyuncs.com:80

相关文档