通过APIM使用SAS Token向私有Azure Blob存储上传大文件请求中断问题排查
问题根因拆解
两个方案的共性触发问题
- APIM默认请求体大小限制不匹配业务场景:Developer/Basic等常用层级默认最大允许的上传请求体仅为10MB/100MB,当上传文件大小超过阈值后,APIM会在请求体传输进度触及上限时主动断开连接,刚好匹配你碰到的“请求发起6-7秒后自动取消、40-70字节小文件可成功上传”的现象。
- 未开启流式透传模式:两个方案都沿用了APIM默认的“全量缓存上传请求体到内存/临时磁盘再转发”的处理逻辑,100MB以上的大文件会快速占满单请求的内存配额,触发进程资源回收断连。你之前验证1GB大文件下载正常,正是因为下载响应默认走流式透传,没有全量缓存的限制,和上传场景的处理逻辑差异导致了体验上的不对称。
- 后端超时阈值默认过低:APIM发往后端的默认超时时间仅为60秒以内,部分实例层默认超时甚至更短,大文件传输未完成就会触发超时断连。
各方案的专属问题
- 方案1的配置问题
- 把携带SAS Token的完整Blob地址直接拼接在
set-backend-service的base-url参数里,同时搭配rewrite-uri template="?",会导致SAS Token中的&、=等签名特殊字符被APIM的URI转义逻辑篡改,最终发往Blob存储的请求签名校验失败。小文件因为体积小、缓存快,会在触发超时前走完头校验流程;大文件因为传输耗时久,会在缓存阶段就被直接断开,看不到实际的签名错误。 - 没有匹配调整透传规则,导致请求路径被错误改写,无法正确命中Blob存储的上传接口。
- 把携带SAS Token的完整Blob地址直接拼接在
- 方案2的配置问题
- 用
set-body>@( context.Request.Body.As<string>() )的逻辑把整个上传请求体转成字符串加载到内存,二进制格式的大文件转字符串后会占用数倍于原文件大小的内存,100MB以上的文件会直接触发内存溢出断连。 send-request默认开启全量请求体缓冲,天生不支持大文件流式转发,单请求的内存开销会随文件大小线性增长。- 配置了
ignore-error="true"同时强制返回200状态码,直接吞掉了所有底层的断连、超时错误,前端只会看到请求被取消,无法定位实际报错。
- 用
修正方向
- 先调整API级基础配置:
- 在对应API的设置页,把请求体大小限制调整为业务需要的阈值(建议设置为2GB,匹配Blob单块上传的最大支持上限)。
- 开启API的
流式请求转发开关,关闭全量请求体缓存,让APIM收到的上传字节直接透传到后端Blob存储,不做本地缓存。 - 在后端配置中把请求超时时间调整为匹配大文件上传的时长,建议设置为15分钟,避免大文件传输中途超时。
- 优化方案1的策略配置(这是最适合大文件上传的实现路径):
- 不要将带SAS Token的完整地址拼入
set-backend-service的base-url,改为将base-url配置为https://{{storageAccountName}}.blob.core.windows.net,后续的容器路径、Blob文件名、SAS Token参数全部通过透传原始请求URI实现,避免特殊字符被转义。 - 移除多余的
rewrite-uri改写逻辑,直接透传原始的请求路径,保证请求能正确命中Blob存储的上传接口。
- 不要将带SAS Token的完整地址拼入
- 方案2不建议用于100MB以上大文件上传场景:
send-request全量缓冲的处理模式天生不适合大文件场景,过高的内存占用会拖累整个APIM实例的响应稳定性,仅适合小体量请求的自定义处理场景。
内容的提问来源于stack exchange,提问作者Satheesh Natarajan
相关产品推荐
相关产品推荐

