Spring Cloud Gateway是否支持上游服务的大文件响应及流式传输?
结论
Spring Cloud Gateway完全支持上游服务的大文件响应,默认就可以实现流式传输,无需将全量文件加载到内存,你遇到的报错是配置或代码写法触发了内存缓存逻辑导致的。
报错原因
你遇到的DataBufferLimitException是因为代码或路由配置中引入了需要把完整响应体读取到内存的操作,比如ModifyResponseBody等修改响应体的过滤器、ProxyExchange调用bodyToMono等方法把全量响应转换成对象,才会触发Spring默认的2MB内存buffer上限限制,哪怕调大上限也只是缓解,没有解决根本问题。
解决方案
方案1:使用原生路由配置(优先推荐)
如果不需要对大文件请求/响应做自定义业务处理,直接用SCG原生路由配置即可,默认就是流式转发:
- 首先确保你的路由规则中没有添加任何需要读取完整请求/响应体的过滤器,避免触发全量缓存逻辑
- 如果需要调整相关配置适配大文件场景,可添加如下配置:
spring: codec: max-in-memory-size: 100MB # 全局编解码内存上限,无特殊业务需求可不配置 cloud: gateway: httpclient: response-timeout: 60000 # 根据文件大小调整响应超时时间,避免传输中断
这种方式下网关仅做流式转发,内存占用稳定,不会随文件大小增长,1GB以上文件也可以正常传输。
方案2:使用ProxyExchange自定义转发
如果必须要通过ProxyExchange做自定义逻辑,需要修改代码避免全量读取响应体到内存,直接将上游返回的数据流原样返回即可,示例代码如下:
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import org.springframework.cloud.gateway.webflux.ProxyExchange; @RestController public class LargeFileProxyController { @GetMapping("/proxy/large-file/**") public Mono<ResponseEntity<Flux<DataBuffer>>> proxyLargeFile(ProxyExchange<Flux<DataBuffer>> exchange) { String upstreamUrl = "你的上游服务地址" + exchange.path(); return exchange.uri(upstreamUrl) .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE) .exchange(clientResponse -> Mono.just( ResponseEntity.status(clientResponse.getStatusCode()) .headers(headers -> headers.putAll(clientResponse.getHeaders().toSingleValueMap())) .body(clientResponse.getBody()) )); } }
内容的提问来源于stack exchange,提问作者jreznot
相关产品推荐
相关产品推荐

