如何配置AWS API Gateway适配SageMaker上Triton的二进制数据协议?
我在AWS SageMaker上部署了基于NVIDIA Triton推理服务器的模型,想通过AWS API Gateway把它以REST API形式暴露给客户端调用。
直接调用SageMaker时,使用特定MIME类型application/vnd.sagemaker-triton.binary+json;json-header-size={NUMBER}能正常工作,这个Content-Type头里的{NUMBER}代表要读取的JSON字节数,后续紧跟二进制数据。
按照AWS官方教程创建了无修改代理到SageMaker Runtime的API,同时将application/vnd.sagemaker-triton.binary+json添加到二进制媒体类型以确保二进制数据无修改传输,但测试API Gateway端点时出现错误:
The error message (unexpected size for input 'np_tensor', expecting 4 additional bytes) suggests that the Triton server is not receiving the correct binary data size, possibly due to the way API Gateway is processing the request.
我推测API Gateway未保留Content-Type=application/vnd.sagemaker-triton.binary+json;json-header-size={NUMBER}这个完整头——直接访问SageMaker端点时省略该头会出现相同错误。日志显示初始请求存在该头,但后续日志为截断输出,无法提供有效信息。
测试用Python客户端代码:
import boto3 import botocore.session from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest import numpy as np import json import requests aws_region = 'us-east-1' # API Gateway URL url = "" # SageMaker Endpoint URL (commented out since we're using API Gateway) # url = "" # Sample dummy input data for testing input_data = np.array([[-0.0024108887]]).astype('float32') # Define the request body for the Triton server json_request = { "inputs": [ { "name": "np_tensor", "shape": list(input_data.shape), "datatype": "FP32", "parameters": {"binary_data_size": input_data.nbytes}, }, ], "outputs": [ {"name": "transcription", "parameters": {"binary_data": True}}, ], } # Convert the request to a JSON string and then to bytes json_request_str = json.dumps(json_request) request_body = json_request_str.encode() + input_data.tobytes() header_length = len(json_request_str) # # Not needed for AWS Gateway # # AWS session and credentials setup # session = boto3.Session() # credentials = session.get_credentials() # # AWS Request with SigV4 Authentication # request = AWSRequest(method="POST", url=url, data=request_body) # SigV4Auth(credentials, 'sagemaker', aws_region).add_auth(request) # signed_headers = dict(request.headers) # Prepare headers, including the custom Content-Type header signed_headers = {} signed_headers["Content-Type"] = "application/vnd.sagemaker-triton.binary+json;json-header-size={}".format(header_length) # Send the request and print the response response = requests.post( url, headers=signed_headers, data=request_body ) print(response.content.decode("utf8"))
我的问题:
- 如何确保AWS Gateway代理请求至SageMaker时保留自定义Content-Type头?
- AWS Gateway是否有额外配置或设置来处理此类请求?
- 是否有人成功配置过类似的AWS Gateway与SageMaker结合使用Triton二进制数据扩展的架构?
1. 确保Content-Type头完整保留
API Gateway默认会传递多数请求头,但带参数的MIME类型可能被特殊处理,需按以下步骤配置:
- 进入API的目标资源→集成请求→HTTP头,添加
Content-Type,映射值设为method.request.header.Content-Type,显式指定传递客户端发送的完整Content-Type头。 - 检查API Gateway的内容编码设置,若开启自动压缩会破坏二进制数据与Content-Type参数的对应关系,建议关闭不必要的压缩配置。
2. API Gateway额外配置要点
- 二进制媒体类型:除了添加
application/vnd.sagemaker-triton.binary+json,需确保API Gateway不对该类型请求做JSON解析或修改,完成配置后要部署到对应阶段生效。 - 集成类型选择:使用HTTP代理集成而非Lambda代理——Lambda代理会对请求进行序列化/反序列化,大概率破坏二进制数据和自定义头结构。集成目标需指向SageMaker Runtime的端点URL(格式为
https://runtime.sagemaker.{region}.amazonaws.com/endpoints/{endpoint-name}/invocations)。 - 全量日志开启:在API Gateway阶段设置中开启详细日志记录,配置CloudWatch日志组,捕获完整请求头和payload,以此验证Content-Type头是否被正确传递到SageMaker。
3. 已验证的可行架构
已有大量用户成功配置同类架构,核心要点如下:
- 用API Gateway的HTTP代理集成直接指向SageMaker端点,避免中间Lambda处理环节。
- 严格配置二进制媒体类型,确保请求以原始二进制形式传递。
- 在集成请求中显式传递所有必要请求头,包括带参数的完整Content-Type。
- 客户端请求需正确签名:若API Gateway启用IAM认证,要么恢复代码中的SigV4签名逻辑,要么在API Gateway上配置API密钥认证替代。
内容的提问来源于stack exchange,提问作者lucidyan

