You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCP Cloud Run返回0字节响应:SpringBoot非阻塞接口排查求助

问题:SpringBoot非阻塞接口在Cloud Run返回0字节响应,但日志显示响应大小正常

我们将Java SpringBoot应用从Heroku迁移至GCP Cloud Run,为优化性能把REST接口改成非阻塞方式后出现异常:相关接口在Cloud Run上返回0字节响应(浏览器、cURL调用均出现此问题),但Cloud Run日志里显示的responseSize是正常的(比如responseSize: "1137")。

已尝试的排查操作(均未解决)

  • 开启公网直接访问Cloud Run,排除负载均衡的影响
  • 将内置容器从Tomcat替换为Jetty,排除容器本身的问题
  • 尝试使用两代不同的Cloud Run实例

该接口在本地开发环境及Docker容器中运行完全正常,仅部署到Cloud Run时出现0字节响应的问题。

更新:cURL详细调用日志(cURL -L -i -v输出)

Trying 34.36.35.1:443...
Connected to ***** (34.36.35.1) port 443 (#0)
ALPN, offering h2
ALPN, offering http/1.1
successfully set certificate verify locations:
CAfile: /etc/ssl/cert.pem
CApath: none
(304) (OUT), TLS handshake, Client hello (1):
(304) (IN), TLS handshake, Server hello (2):
(304) (IN), TLS handshake, Unknown (8):
(304) (IN), TLS handshake, Certificate (11):
(304) (IN), TLS handshake, CERT verify (15):
(304) (IN), TLS handshake, Finished (20):
(304) (OUT), TLS handshake, Finished (20):
SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
ALPN, server accepted to use h2
Server certificate:
subject: CN=***********
start date: Jun 15 15:58:36 2023 GMT
expire date: Sep 13 16:52:50 2023 GMT
subjectAltName: host "***********" matched cert's "*"
issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1D4
SSL certificate verify ok.
Using HTTP2, server supports multiplexing
Connection state changed (HTTP/2 confirmed)
Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
Using Stream ID: 1 (easy handle 0x12c00e000)
GET /api/user/permissions HTTP/2
Host: *************
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/114.0
// 部分无关请求头已省略
< HTTP/2 200 
< vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding,User-Agent
< cache-control: no-cache, must-revalidate, no-transform,no-store
< x-content-type-options: nosniff
< x-xss-protection: 1; mode=block
< referrer-policy: origin-when-cross-origin
< content-type: application/json
< x-cloud-trace-context: 1dfe301ceac344ebb4b30eed4c89a495;o=1
< date: Wed, 05 Jul 2023 16:02:11 GMT
< server: Google Frontend
< content-length: 0
< via: 1.1 google
< strict-transport-security: 31536000
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
Connection #0 to host ************ left intact

可能的原因

  1. HTTP/2协议兼容性问题:从cURL日志看,Cloud Run使用HTTP/2协议,非阻塞接口的响应流处理可能在HTTP/2分帧机制下存在适配异常——比如响应流未正确关闭、分帧标记缺失,导致Google Frontend(GFE)无法识别完整响应体,最终返回content-length:0,但容器内部日志仅记录了已写入的字节数。
  2. 非阻塞响应未正确完成:Spring WebFlux的非阻塞接口如果返回的Flux/Mono未触发onComplete信号,容器会认为响应未完成,但Cloud Run日志仍会记录已写入的字节数,GFE则会因未收到完整信号截断响应。
  3. 响应头与响应体不匹配:代码中若手动设置了Content-Length但实际响应体大小不符,或非阻塞框架自动处理响应头时出现异常,会导致GFE忽略响应体。
  4. Cloud Run CPU分配策略影响:若实例采用请求触发的CPU分配(而非持续分配),非阻塞响应流处理过程中CPU被回收,可能导致响应未完整发送。

等待官方支持期间的排查方向

  • 强制使用HTTP/1.1测试:用cURL添加--http1.1参数调用接口,验证是否是HTTP/2兼容性问题:
    curl -L -i -v --http1.1 https://<你的Cloud Run域名>/api/user/permissions
    
  • 检查非阻塞接口代码:
    • 确认返回的Mono/Flux是否正确终止(无无限流、已触发完成信号);
    • 排查自定义拦截器/过滤器是否消耗了响应流但未正确传递。
  • 添加容器内响应日志:在应用中记录响应体生成、写入及完成信号的触发细节,对比Cloud Run日志的responseSize,确认容器内是否生成了完整响应。
  • 测试极简非阻塞接口:编写仅返回固定字符串的极简非阻塞接口(如return Mono.just("{\"test\":1}")),部署后验证是否能正常返回响应,排除业务逻辑干扰。
  • 调整Cloud Run实例配置:将实例CPU设置为"持续分配",验证是否因CPU回收导致响应中断。
  • 捕获容器内网络流量:在容器内使用tcpdump捕获发送给GFE的响应数据包,确认容器是否确实发送了完整响应体。

内容的提问来源于stack exchange,提问作者enterbios

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 02:17:39