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

rbl8hiat  于 2023-08-02  发布在  Java
关注(0)|答案(3)|浏览(112)

我一直在尝试让GRPC的负载平衡在我部署到Kubernetes集群的Java应用程序中工作,但我没有太大的成功。似乎没有太多关于这个的文档,但从在线示例中,我可以看到,我现在应该能够在设置ManagedChannel时使用'.defaultLoadBalancingPolicy(“round_robin”)'(在GRPC Java lib的后续版本中)。
更具体地说,我使用的是1.34.1版的GRPC Java库。我创建了两个Sping 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作为无头服务,以便实现GRPC负载均衡。
为了测试失败的请求,我做了两件事:

  • 在测试运行的执行期间终止GRPC-接收器吊舱中的一个-例如当我已经请求grpc发送方发送比如5000个请求到grpc接收方时。Grpc-sender检测到pod已经被杀死,并刷新其接收器pod列表,并将未来的请求路由到新的pod。正如预期的那样,在pod终止过程中的一些请求失败,GRPC状态为UNAVAILABLE。
  • 在grpc接收器中有一些简单的逻辑,它生成一个随机数,如果该随机数低于0.2,则返回Grpc Status INTERNAL而不是OK。

通过以上两种方法,我可以在测试运行期间使一部分请求失败。现在我正在尝试让GRPC的重试机制工作。通过阅读稀疏的文档,我正在做以下工作:

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


然而,这似乎没有任何效果,我看不到失败的请求被重试。
我看到这仍然被标记为@ExperimentalApi特性,那么它应该像预期的那样工作吗?它已经实现了吗?
如果是这样的话,有没有什么明显的东西我错过了?我还需要做什么来让重试工作?
有没有更详细地解释如何做到这一点的文档?
非常感谢提前…

esyap4oy

esyap4oy1#

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中得到了澄清

vom3gejh

vom3gejh2#

非常感谢@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。成熟度如何,是否适合用于生产?它是否可能发生巨大变化?

vlju58qv

vlju58qv3#

确实,如何配置客户端来进行重试并不明显。此外,您必须设置name.service才能使其工作。我们使用Kotlin,有一个例子:

NettyChannelBuilder
    .forAddress("localhost", 7001)
    .usePlaintext()
    .defaultServiceConfig(
        mapOf(
            "methodConfig" to listOf(
                mapOf(
                    "name" to listOf(mapOf("service" to "TestService")),
                    "retryPolicy" to mapOf(
                        "maxAttempts" to "10",
                        "initialBackoff" to "0.5s",
                        "maxBackoff" to "10s",
                        "backoffMultiplier" to 1.2,
                        "retryableStatusCodes" to listOf("UNAVAILABLE")
                    )
                )
            )
        )
    )
    .maxRetryAttempts(10)
    .enableRetry()
    .build()

字符串

相关问题