- 模型推理服务
- AI 应用
- 后端
【免费下载链接】server
The Triton Inference Server provides an optimized cloud and edge inferencing solution.
本指南系统讲解 Triton Inference Server 的
binary_tensor_data扩展:如何在 HTTP/REST 推理请求与响应中以二进制形式传输张量数据,包括binary_data_size、binary_data、binary_data_output三个核心参数的使用方式、Inference-Header-Content-Length头的语义,以及不携带推理头 JSON 的 Raw Binary 请求模式。读完本文,你将能够手写任意数据类型的二进制推理请求、正确解析二进制响应,并理解该扩展在 src/http_server.cc 中的底层实现与边界校验逻辑。
一、扩展概述:为什么需要二进制张量数据
Triton Inference Server 默认通过 HTTP/REST 的 JSON 表示来承载张量数据:每个输入/输出张量的数据都以数组形式嵌入 JSON 对象。当张量元素数量庞大(例如图像、嵌入向量、大 Batch 推理结果)时,JSON 文本编码会带来双重开销——datatype到文本的转换开销与体积膨胀。
Binary Tensor Data Extension 允许在 HTTP 请求/响应体中,在 JSON 对象之后直接追加一段原始二进制数据来承载张量内容,从而:
- 消除 JSON 数组中数字到文本的编解码开销;
- 大幅缩减请求/响应体体积(数值类型二进制表示通常比文本表示小 3~5 倍);
- 保持 HTTP/REST 协议的简单性,同时获得接近 gRPC 的传输效率。
由于该扩展受支持,Triton 会在其 Server Metadata 的extensions字段中报告"binary_tensor_data",客户端可据此探测服务器能力。
二、二进制数据的组织方式与编码规则
当张量以二进制形式传输时,数据遵循以下严格的组织约定(由 src/http_server.cc 中CheckBinaryInputData/ReadDataFromJson/WriteDataToJson等实现印证):
- 字节序:小端序(little-endian);
- 内存布局:按行主序(row-major)连续排列,元素之间无 stride、无 padding;
- 数据类型:所有支持的数据类型都以该类型的原生字节宽度表示;
- BOOL 类型:
true为单个值为1的字节,false为单个值为0的字节; - BYTES 类型:每个元素由「4 字节无符号整数长度 + 实际字节内容」组成,即每个元素都带有一个
uint32长度前缀。
BYTES 类型的这一编码在响应序列化中有直接证据:
src/http_server.cc的WriteDataToJson分支(针对TRITONSERVER_TYPE_BYTES)逐元素读取uint32_t长度前缀后再取对应字节;在 qa/L0_http/http_test.py 的test_byte用例中,客户端解析原始二进制输出时也通过r.content[header_size + 4:]跳过 4 字节长度前缀来还原字符串。
三、三个核心参数详解
二进制扩展通过请求 JSON 中的parameters字段控制数据传输方式,共涉及三个参数:
1.binary_data_size(int64)——输入/输出张量以二进制发送
出现在$request_input(请求输入)与$response_output(响应输出)的parameters中,表示该张量二进制数据占用的字节数。只要该参数存在,即宣告该张量以二进制形式传递。
从源码看,src/http_server.cc 的CheckBinaryInputData(约 L944-963)在输入的parameters中查找binary_data_size,将其解析为无符号整数作为byte_size,一旦命中即置is_binary = true;而ValidateInputContentType(约 L1045-1085)强制要求每个输入在data(JSON 内联数据)、binary_data_size(二进制数据)、shared_memory_region(共享内存)三者中只能且必须设置一个,否则返回INVALID_ARG错误。
2.binary_data(bool)——指定某个输出以二进制返回
出现在$request_output的parameters中,取值为true表示该输出应返回二进制数据,false或省略表示该输出以 JSON 返回。
对应的CheckBinaryOutputData(src/http_server.cc L965-981)解析该布尔值;同时ValidateOutputParameter(约 L1087-1119)校验:输出不能同时设置shared_memory_region与binary_data: true,否则报错。
3.binary_data_output(bool)——请求级全局默认
出现在$inference_request顶层的parameters中,为true时表示所有输出默认以二进制返回,除非某个输出通过自身的binary_data参数覆盖此设置。
源码中ParseJsonTritonParams(src/http_server.cc L2894-2984)在遍历请求级参数时识别binary_data_output,将其解析为布尔值并赋给infer_req->alloc_payload_.default_output_kind_(BINARY或JSON),作为未显式列出输出时的全局默认输出格式。
四、请求/响应体结构:JSON 头 + 二进制数据尾
当一个或多个张量以二进制通信时,HTTP 请求或响应体由两部分拼接而成:
- JSON 推理请求/响应对象(位于体首);
- 按 JSON 中张量声明顺序排列的二进制数据块(紧跟在 JSON 之后)。
此时必须提供Inference-Header-Content-Length头,其值为 JSON 对象的字节长度;而标准 HTTP 的Content-Length继续表示整个请求/响应体的总长度(即 JSON 长度 + 全部二进制数据长度)。
服务端在 src/http_server.cc 的GetInferenceHeaderLength(约 L2490-2534)解析该头:若未提供则默认取整个Content-Length;提供时校验其取值必须落在(0, Content-Length]区间内,否则返回INVALID_ARG。测试用例qa/L0_http/http_test.py的test_inference_header_content_length_out_of_range专门验证了该边界。响应侧,SetResponseHeader(约 L4376-4405)在存在二进制数据时将Content-Type设为application/octet-stream并回写Inference-Header-Content-Length;无二进制数据时Content-Type为application/json。
五、Binary Tensor Request 实战示例
下面是一个将输入以二进制发送、并要求输出也以二进制返回的完整请求。两个输入张量二进制数据合计 19 字节(16 + 3),必须计入Content-Length:
POST /v2/models/mymodel/infer HTTP/1.1 Host: localhost:8000 Content-Type: application/octet-stream Inference-Header-Content-Length: <xx> Content-Length: <xx+19> { "model_name" : "mymodel", "inputs" : [ { "name" : "input0", "shape" : [ 2, 2 ], "datatype" : "UINT32", "parameters" : { "binary_data_size" : 16 } }, { "name" : "input1", "shape" : [ 3 ], "datatype" : "BOOL", "parameters" : { "binary_data_size" : 3 } } ], "outputs" : [ { "name" : "output0", "parameters" : { "binary_data" : true } } ] } <16 bytes of data for input0 tensor> <3 bytes of data for input1 tensor>input0形状[2, 2]、类型UINT32,4 个元素 × 4 字节 = 16 字节二进制数据;input1形状[3]、类型BOOL,3 个元素 × 1 字节 = 3 字节二进制数据;outputs中的binary_data: true要求output0以二进制返回。
假设模型返回形状[3, 2]、类型FP32的张量(6 元素 × 4 字节 = 24 字节),响应如下:
HTTP/1.1 200 OK Content-Type: application/octet-stream Inference-Header-Content-Length: <yy> Content-Length: <yy+24> { "outputs" : [ { "name" : "output0", "shape" : [ 3, 2 ], "datatype" : "FP32", "parameters" : { "binary_data_size" : 24 } } ] } <24 bytes of data for output0 tensor>注意响应 JSON 中 Triton 会为二进制输出自动填入binary_data_size(见 src/http_server.cc L4301-4311:BINARY类型的输出在parameters中写入binary_data_size为实际字节数,并将对应输出缓冲加入ordered_buffers,最终按序追加到 JSON 之后)。
六、Raw Binary Request:不携带推理头的裸二进制请求
对于张量元数据可由二进制数据字节数直接推导的模型,客户端可以进一步省去推理头 JSON,请求体仅包含张量的二进制数据。判定条件为:
- 模型只有一个输入;
- 输入数据类型非
BYTES时,可变维度数量至多 1 个(即除已知维度外只有一个维度可由字节数反推);输入数据类型为BYTES时,形状必须为[1]; - 支持的数据类型范围与 KServe Predict V2 协议定义的张量数据类型一致。
发送裸二进制请求时,Inference-Header-Content-Length头必须显式给出,且值为 0,用以声明请求体不包含推理头 JSON。
服务端逻辑位于 src/http_server.cc 的EVRequestToJsonImpl(约 L3004-3106):当header_length == 0时,整个 HTTP 体都被视为原始输入数据,随后EVBufferToRawInput(约 L3108 起)为该请求添加名为raw_input的原始输入,并校验字节数不超过--http-max-input-size限制。形状推导失败(多输入、BYTES 多元素、多可变维度)时返回 400 错误,错误信息可参见 qa/L0_http/http_test.py 中的test_byte_too_many_elements、test_multi_variable_dimensions、test_multi_inputs等用例断言。
使用裸二进制请求时还需注意两个语义:
- 若模型支持 batching,由于推理头被省略,请求会被视为batch-1请求;
- 模型所有输出都将以二进制张量形式返回(等效于请求级设置了
binary_data_output: true)。
Raw Binary Request 示例
以下请求体为 16 字节输入数据,Content-Length即总长:
POST /v2/models/mymodel/infer HTTP/1.1 Host: localhost:8000 Content-Type: application/octet-stream Inference-Header-Content-Length: 0 Content-Length: 16 <16 bytes of data for input tensor>假设模型返回两个输出,形状均为[3, 1]、类型FP32(各 12 字节),响应为:
HTTP/1.1 200 OK Content-Type: application/octet-stream Inference-Header-Content-Length: <yy> Content-Length: <yy+24> { "outputs" : [ { "name" : "output0", "shape" : [ 3, 1 ], "datatype" : "FP32", "parameters" : { "binary_data_size" : 12 } }, { "name" : "output1", "shape" : [ 3, 1 ], "datatype" : "FP32", "parameters" : { "binary_data_size" : 12 } } ] } <12 bytes of data for output0 tensor> <12 bytes of data for output1 tensor>七、源码级实现剖析:二进制输入的处理链路
在服务端,二进制输入从 HTTP 体解析到推理请求的完整调用链为:
EVRequestToJsonImpl / EVBufferToJson(切分 JSON 头) → ParseJsonTritonRequestID(解析 id) → ParseJsonTritonParams(解析请求级参数,含 binary_data_output) → ParseJsonTritonIO(逐输入处理,含二进制数据搬运)在ParseJsonTritonIO(src/http_server.cc L2572 起)中,对每个输入:
- 先调用
ValidateInputContentType校验数据来源唯一性; - 调用
CheckBinaryInputData解析binary_data_size得到byte_size; - 若为二进制输入且
byte_size == 0,直接追加空数据(支持零形状张量); - 否则若
header_length == 0(即请求被当作裸二进制请求)会返回INVALID_ARG错误——提示必须同时提供有效的Inference-Header-Content-Length与binary_data_size; - 随后通过
evbuffer_iovec分块消费请求体中的二进制数据:逐块调用TRITONSERVER_InferenceRequestAppendInputData将数据以TRITONSERVER_MEMORY_CPU追加进推理请求,直至消费完byte_size字节;若请求体不足以满足声明的大小,则返回「unexpected size for input ... expecting N additional bytes」错误。
八、客户端验证与最佳实践
仓库测试对二进制扩展覆盖相当完整,可作为客户端实现的参考:
- qa/L0_http/http_test.py:
test_raw_binary/test_raw_binary_longer用numpy.tobytes()生成 FP32 输入、以Inference-Header-Content-Length: 0发送,并用响应头中的Inference-Header-Content-Length定位输出二进制数据的起始偏移;test_byte验证 BYTES 类型的 4 字节长度前缀;test_content_encoding_chunked_manually验证 chunked 编码下裸二进制请求同样可用; - qa/L0_http/http_request_many_chunks.py:验证输入分多个块传输时服务端按
binary_data_size精确切分消费; - qa/L0_http/http_input_size_limit_test.py:验证
--http-max-input-size对二进制输入的字节数上限约束。
实践要点总结:
- 二进制输入必须在
parameters中给出精确的binary_data_size,且与Content-Length中的实际数据字节数一致; - 只要请求/响应含二进制数据,就必须携带
Inference-Header-Content-Length(普通二进制请求为其 JSON 头长度,裸二进制请求为0); - 解析二进制响应时,先读
Inference-Header-Content-Length得到 JSON 头偏移,再按输出声明顺序从该偏移开始依次读取各输出的原始字节; - 对于 BYTES 类型输出,需按「4 字节长度前缀 + 内容」逐元素解析;
- 仅在模型满足「单输入、形状可由字节数推导」条件时使用 Raw Binary Request,否则退化为携带完整 JSON 头的普通二进制请求。
九、相关文档与进一步阅读
- 本扩展所属协议目录:docs/protocol(含分类、generate、共享内存、序列等扩展的并行说明)
- 扩展二进制数据在 HTTP 服务端的完整实现:src/http_server.cc
- 二进制输入限制校验与参数解析辅助函数:
CheckBinaryInputData、CheckBinaryOutputData、ValidateInputContentType、ValidateOutputParameter(均位于 src/http_server.cc) - 推理协议的整体说明与 gRPC/HTTP 端点约定:docs/protocol/README.md
- KServe Predict V2 协议张量数据类型定义可作为 Raw Binary 请求支持类型的参考依据
- 模型推理服务
- AI 应用
- 后端
【免费下载链接】server
The Triton Inference Server provides an optimized cloud and edge inferencing solution.
相关推荐
Triton Inference Server 统计扩展(Statistics Extension)协议深度解析:HTTP/REST 与 gRPC 接口全解
Triton Inference Server 统计扩展(Statistics Extension)协议深度解析:HTTP/REST 与 gRPC 接口全解 T
模型推理服务AI 应用后端Triton Inference Server 的 KServe 协议扩展全景:从 HTTP/REST 到 gRPC 的 11 个扩展机制详解
Triton Inference Server 的 KServe 协议扩展全景:从 HTTP/REST 到 gRPC 的 11 个扩展机制详解 导读 Trito
模型推理服务AI 应用后端如何在Triton Inference Server中实现自定义元数据传递:推理协议扩展终极指南
如何在Triton Inference Server中实现自定义元数据传递:推理协议扩展终极指南 Triton Inference Server是一款由NVID
模型推理服务AI 应用后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考