11450个活跃Spanner会话是否引发内存/超时问题?求排查指引
Spanner高活跃会话引发SpringBoot Pod内存问题(错误码137)及存活探针超时的排查方案
问题关联确认
11450个Spanner活跃会话肯定会引发你遇到的内存溢出和存活探针超时问题:
- 每个Spanner会话在SpringBoot客户端进程中会占用内存存储连接状态、事务上下文、元数据缓存等数据,过万级别的会话会快速耗尽容器内存,触发K8s的OOM Killer,导致容器以错误码137终止(这是OOM Killer终止进程的典型返回码)。
- 大量活跃会话会挤占应用的CPU和内存资源,导致存活探针的检查请求无法被及时处理,超时后K8s会重启Pod。
排查与修复步骤
1. 定位会话泄漏根源
- 检查应用中Spanner客户端的会话管理逻辑:确认是否存在未正确关闭会话/事务的场景,比如事务完成后未调用
close()方法,或者复用会话的逻辑存在漏洞。 - 查看应用日志,统计会话创建与销毁的频次,对比两者的速率差,验证是否存在会话泄漏。
- 执行命令
gcloud spanner databases sessions list --instance my-instance --database my-db --format="value(createTime)",分析会话的创建时间分布,判断是否有突发的会话创建高峰。
2. 优化Spanner客户端会话池配置
- 限制最大会话数:如果使用Spring Cloud GCP,在
application.yml中设置spring.cloud.gcp.spanner.session-pool.max-size(建议从200-500开始,根据业务负载调整);如果直接使用Spanner Java客户端,通过SessionPoolOptions.builder().setMaxSessions(N)配置。 - 启用空闲会话回收:设置会话空闲超时时间,让客户端自动清理闲置会话,比如配置
spring.cloud.gcp.spanner.session-pool.idle-timeout为5-10分钟,避免资源浪费。
3. 分析JVM内存占用
- 在容器内执行
jmap -histo <spring-boot-pid>,查看com.google.cloud.spanner.Session相关对象的数量,确认是否存在大量未回收的会话实例。 - 生成堆转储文件:执行
jmap -dump:format=b,file=heap.hprof <spring-boot-pid>,用JProfiler或VisualVM分析堆转储,追踪会话对象的引用链,定位泄漏点。
4. 调整K8s存活探针配置
- 临时延长探针的超时和周期,避免在会话清理阶段频繁重启Pod,示例配置:
livenessProbe: httpGet: path: /actuator/health port: 8080 initialDelaySeconds: 60 periodSeconds: 30 timeoutSeconds: 10 - 确保健康检查接口(如
/actuator/health)实现轻量化,不要依赖Spanner连接,防止因会话问题导致健康检查失败。
5. 建立监控告警
- 配置监控跟踪Spanner活跃会话数、容器内存/CPU使用率,设置告警阈值(比如会话数超过500时触发告警)。
- 监控K8s的OOM事件,确认会话优化后内存占用是否恢复正常。
内容的提问来源于stack exchange,提问作者Dakshin Rajavel
相关产品推荐
相关产品推荐

