微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Kubernetes 集群中使用 grpc-java 使 GRPC 的重试机制起作用?

如何解决如何在 Kubernetes 集群中使用 grpc-java 使 GRPC 的重试机制起作用?

我一直试图在部署到 Kubernetes 集群的 Java 应用程序中实现 GRPC 的负载平衡,但我并没有取得太大的成功。似乎没有太多关于此的文档,但是从在线示例中我可以看到我现在应该能够在设置 ManagedChannel 时使用 '.defaultLoadBalancingPolicy("round_robin")'(在 GRPC Java lib 的更高版本中) .

更具体地说,我使用的是 GRPC Java 库的 1.34.1 版。我创建了两个 Spring Boot (v2.3.4) 应用程序,一个叫做 grpc-sender,一个叫做 grpc-receiver。

grpc-sender 充当 GRPC 客户端并定义(Netty)ManagedChannel 为:

@Bean
public ManagedChannel greetingServiceManagedChannel() {
  String host = "grpc-receiver";
  int port = 6565;
  return NettyChannelBuilder.forAddress(host,port)
      .defaultLoadBalancingPolicy("round_robin")
      .usePlaintext().build();
}

然后 grpc-receiver 充当 GRPC 服务器:

Server server = ServerBuilder.forPort(6565)
        .addService(new GreetingServiceImpl()).build();

我正在将这些应用部署到一个 Kubernetes 集群(暂时在 minikube 本地运行),并且我为 grpc-receiver 应用创建了一个 Service 作为 headless 服务,这样就可以实现 GRPC 负载均衡。

为了测试失败的请求,我做了两件事:

  • 在执行测试运行期间杀死其中一个 grpc-receiver pod - 例如当我请求 grpc-sender 向 grpc-receiver 发送 5000 个请求时。 Grpc-sender 确实检测到 pod 已被杀死并刷新其接收者 pod 列表,并将未来的请求路由到新的 pod。正如预期的那样,在终止 Pod 期间进行的一些请求失败,并显示 GRPC 状态不可用。
  • 在 grpc-receiver 中有一些简单的逻辑来生成一个随机数,如果该随机数低于 0.2,则返回 Grpc Status INTERNAL 而不是 OK。

通过以上两种方式,我可以在测试运行期间获得一定比例的请求失败。现在我试图让 GRPC 的重试机制起作用。通过阅读稀疏文档,我正在执行以下操作:

return NettyChannelBuilder.forAddress(host,port)
        .defaultLoadBalancingPolicy("round_robin")
        .enableRetry()
        .maxRetryAttempts(10)
        .usePlaintext().build();

然而,这似乎没有效果,我根本看不到失败的请求被重试。

我看到这仍然被标记为@ExperimentalApi 功能,那么它是否应该按预期工作并已实施?

如果是这样,我是否遗漏了一些明显的东西?我还需要做些什么才能使重试工作正常进行?

是否有任何文档更详细地解释了如何执行此操作?

非常感谢...

解决方法

ManagedChannelBuilder.enableRetry().maxRetryAttempts(10) 不足以进行重试。重试需要定义了 RetryPolicy 的服务配置。一种方法是使用 RetryPolicy 设置默认服务配置,请参阅 https://github.com/grpc/grpc-java/tree/v1.35.0/examples

中的重试示例

关于 maxRetryAttempts() 的 javadoc 有一些混淆,它在 https://github.com/grpc/grpc-java/pull/7803

中得到了澄清 ,

非常感谢@user675693!效果很好:)

maxRetryAttempts() 的工作确实有点混乱。

从文档中我可以看到:

“必须指定 maxAttempts,并且必须是大于 1 的 JSON 整数值。大于 5 的值被视为 5,不会被视为验证错误。”

参考服务配置中的 maxAttempts。如果我们想要超过 5 次尝试,我可以将其设置为 maxRetryAttempts(10) 例如在我的 ManagedChannel 设置中:

return NettyChannelBuilder.forAddress(host,port)
        .defaultLoadBalancingPolicy("round_robin")
        .defaultServiceConfig(config)
        .enableRetry()
        .maxRetryAttempts(10)
        .usePlaintext().build();

但要正确使用该设置,我需要在服务配置和 ManagedChannel 设置代码中将其设置为 10,否则只执行 5 次重试。从 Javadoc 或文档中并不清楚,但这就是我的测试中发生的情况。

另外,这个重试功能被标记为@ExperimentalApi。成熟到什么程度,是否适合在生产中使用?它可能会发生巨大变化吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。