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

java-spanner升级至6.45.0后DEADLINE_EXCEEDED重试失效求助

DEADLINE_EXCEEDED重试失效问题排查与解决

从java-spanner 6.38.2(gax 2.24)升级到6.45.0(gax 2.32)后出现的DEADLINE_EXCEEDED不重试问题,大概率和GAX版本升级带来的重试逻辑调整有关,以下是具体分析和解决方向:

核心原因推测

GAX 2.24到2.32版本间,对DEADLINE_EXCEEDED的重试判定逻辑做了细分:

  • 旧版本中,客户端触发的RPC超时(比如InitialRpcTimeout到期)和后端返回的DEADLINE_EXCEEDED都会被纳入重试范围,只要你将该code加入retryableCodes。
  • 新版本中,默认的重试Predicate会区分超时来源:仅后端返回的DEADLINE_EXCEEDED会被重试,客户端本地触发的RPC超时会被过滤掉,即使你显式添加了DEADLINE_EXCEEDED到retryableCodes。

排查步骤

  1. 确认超时类型
    在捕获异常时,打印状态码的详细信息,区分是客户端超时还是后端返回的超时:

    catch (SpannerException e) {
        System.out.println("Status code: " + e.getStatusCode());
        System.out.println("Error message: " + e.getMessage());
        System.out.println("Cause: " + e.getCause());
    }
    

    如果日志中出现类似"Timeout exceeded while waiting for rpc"的信息,说明是客户端本地触发的RPC超时,这是新版本中默认不重试的场景。

  2. 检查全局超时配置冲突
    确认是否在构建Spanner客户端时设置了全局级别的deadline,比如:

    SpannerOptions.newBuilder()
        .setSessionTimeout(Duration.ofMillis(100)) // 这个会覆盖Stub级别的重试超时
        .build();
    

    全局超时如果小于你的重试总超时(2000ms),会导致第一次RPC超时后直接终止请求,无法触发重试。

  3. 验证重试配置是否生效
    在客户端构建完成后,打印Stub的重试配置,确认DEADLINE_EXCEEDED确实在可重试列表中:

    ReadSettings readSettings = settingsBuilder.build().readSettings();
    System.out.println("Retryable codes: " + readSettings.getRetryableCodes());
    System.out.println("Retry settings: " + readSettings.getRetrySettings());
    

解决方法

1. 自定义RetryPredicate覆盖默认逻辑

显式设置RetryPredicate,明确将所有DEADLINE_EXCEEDED(无论客户端还是后端触发)纳入重试范围:

settingsBuilder.readSettings()
    .setRetryPredicate(status -> {
        StatusCode.Code code = status.getCode();
        return code == StatusCode.Code.DEADLINE_EXCEEDED 
            || code == StatusCode.Code.UNAVAILABLE;
    })
    .setRetrySettings(
        RetrySettings.newBuilder()
            .setInitialRetryDelay(Duration.ofMillis(10))
            .setMaxRetryDelay(Duration.ofMillis(200))
            .setRetryDelayMultiplier(1.5)
            .setInitialRpcTimeout(Duration.ofMillis(100))
            .setMaxRpcTimeout(Duration.ofMillis(1000))
            .setRpcTimeoutMultiplier(1.5)
            .setTotalTimeout(Duration.ofMillis(2000))
            .build());

2. 调整全局超时配置

如果存在全局deadline设置,确保其值不小于重试总超时(2000ms),或者直接移除全局超时配置,改用Stub级别的重试控制。

3. 确认配置未被覆盖

检查客户端构建流程,确保settingsBuilder的配置没有被后续代码覆盖,比如某些框架或工具类可能会重置Stub的设置。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 23:02:04