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

如何配置Istio以忽略特定gRPC错误(记录未找到)的重试?

解决gRPC调用中"记录未找到"场景不重试的方案

第一步:优化gRPC错误类型(推荐)

当前使用的UNKNOWN(错误码2)属于通用错误,不利于精准区分场景。建议改成gRPC标准的NOT_FOUND(错误码5),这是语义明确的资源不存在错误,后续重试逻辑更容易精准匹配。

修改后gRPC返回的错误格式类似:

Error: 5 NOT_FOUND: record not found

第二步:在REST API的gRPC客户端中配置重试规则

根据你使用的gRPC客户端框架,针对性配置重试拦截器或策略,排除NOT_FOUND(或你指定的错误码)的重试。

示例1:Go语言(grpc-go)

使用官方重试拦截器,通过自定义判定函数排除NOT_FOUND错误:

import (
    "context"
    "google.golang.org/grpc"
    "google.golang.org/grpc/codes"
    "google.golang.org/grpc/status"
    grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
)

// 自定义重试判定逻辑
retryFilter := func(ctx context.Context, err error) bool {
    s, ok := status.FromError(err)
    if !ok {
        return false
    }
    // 仅非NOT_FOUND错误触发重试
    return s.Code() != codes.NotFound
}

// 创建带重试拦截器的gRPC客户端连接
conn, err := grpc.Dial(
    "grpc-server-address:port",
    grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(
        grpc_retry.WithMax(3), // 最大重试次数
        grpc_retry.WithRetryOn(retryFilter),
    )),
)

示例2:Java语言(grpc-java)

通过RetryPolicy指定可重试的错误码,排除NOT_FOUND:

import io.grpc.Status;
import io.grpc.retry.RetryPolicy;

RetryPolicy retryPolicy = RetryPolicy.newBuilder()
    .setMaxAttempts(3)
    .addRetryableStatusCode(Status.Code.UNAVAILABLE)
    .addRetryableStatusCode(Status.Code.RESOURCE_EXHAUSTED)
    // 不添加NOT_FOUND,即该错误不触发重试
    .build();

// 将重试策略绑定到Stub
MyServiceStub stub = MyServiceGrpc.newStub(channel)
    .withRetryPolicy(retryPolicy);

示例3:Python语言(grpcio)

使用RetryInterceptor自定义重试条件:

import grpc
from grpc import StatusCode

def retry_predicate(attempt_state):
    # 获取错误状态码,排除NOT_FOUND
    return attempt_state.exception.code() != StatusCode.NOT_FOUND

# 创建带重试拦截器的客户端
interceptor = grpc.retry.RetryInterceptor(
    max_attempts=3,
    retry_predicate=retry_predicate,
)
with grpc.insecure_channel('grpc-server-address:port') as channel:
    stub = MyServiceStub(channel)
    # 调用时应用拦截器
    response = stub.MyMethod(request, interceptors=[interceptor])

第三步:兜底处理(若无法修改gRPC错误码)

如果暂时不能调整gRPC错误码,可通过错误消息文本匹配排除重试(注意:此方式依赖文本内容,不够健壮,仅作临时方案):

// 伪代码逻辑
function shouldRetry(err) {
    if (err.message.includes("record not found")) {
        return false; // 不重试
    }
    // 其他符合重试条件的错误返回true
    return isRetryableError(err);
}

关键注意事项

  • 优先使用标准gRPC错误码,语义明确且兼容各客户端框架,避免依赖文本匹配。
  • 确保重试拦截器仅作用于需要重试的gRPC方法,不要全局强制所有调用都重试。
  • 测试时需覆盖"记录未找到"场景,验证是否确实不触发重试,同时确保其他可重试错误(如服务不可用)仍能正常重试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 08:13:09