我一直在尝试让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特性,那么它应该像预期的那样工作吗?它已经实现了吗?
如果是这样的话,有没有什么明显的东西我错过了?我还需要做什么来让重试工作?
有没有更详细地解释如何做到这一点的文档?
非常感谢提前…
3条答案
按热度按时间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中得到了澄清
vom3gejh2#
非常感谢@user675693!效果非常好:)
maxRetryAttempts()的工作方式确实有点令人困惑。
从文档中我可以看到:
“必须指定maxAttempts,且必须是大于1的JSON整数值。大于5的值将被视为5,而不被视为验证错误。”
指的是服务配置中的maxAttempts。如果我们希望尝试次数超过5次,我可以将其设置为maxRetryAttempts(10),例如在我的ManagedChannel设置中:
字符串
但是,为了正确使用该设置,我需要在服务配置和ManagedChannel设置代码中将其设置为10,否则只会执行5次重试。从Javadoc或文档中并不清楚,但从我的测试中似乎就是这样。
此外,此重试功能标记为@ExperimentalApi。成熟度如何,是否适合用于生产?它是否可能发生巨大变化?
vlju58qv3#
确实,如何配置客户端来进行重试并不明显。此外,您必须设置name.service才能使其工作。我们使用Kotlin,有一个例子:
字符串