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



我一直在尝试让GRPC的负载平衡在部署到Kubernetes集群的Java应用程序中发挥作用,但我没有取得太大成功。关于这一点,似乎没有太多的文档,但从网上的例子中,我可以看到,在设置ManagedChannel(在GRPC Java lib的更高版本中(时,我现在应该能够使用".defaultLoadBalancingPolicy("round_robin"("。

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

grpc发送方充当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接收器充当grpc服务器:

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

我正在将这些应用程序部署到Kubernetes集群(暂时在minikube本地运行(,并为grpc接收器应用程序创建了一个服务,作为无头服务,以便实现grpc负载平衡。

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

  • 在执行测试运行期间杀死其中一个grpc-receiver pod,例如,当我请求grpc-sender向grpc-receive发送5000个请求时。Grpc发送器确实检测到pod已被杀死,并刷新其接收器pod列表,并将未来的请求路由到新的pod。正如预期的那样,在吊舱终止期间飞行中的一些请求失败,GRPC状态不可用
  • 在grpc接收器中有一些简单的逻辑,它生成一个随机数,如果该随机数低于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。它有多成熟,适合用于生产吗?它可能会发生巨大变化吗?

确实,如何配置客户端进行重试并不明显。此外,您必须设置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()

最新更新