![](/img/trans.png)
[英]How to get GRPC's retry mechanism to work using grpc-java in Kubernetes cluster?
[英]How to get GRPC's round_robin load balancing to work using grpc-java in Kubernetes cluster?
我一直在尝试让 GRPC 的负载平衡在部署到 Kubernetes 集群的 Java 应用程序中工作,但我并没有取得太大的成功。 似乎没有太多关于此的文档,但从在线示例中我可以看到我现在应该能够在设置 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 应用程序创建了一个服务作为无头服务:
kind: Service
apiVersion: v1
metadata:
name: grpc-receiver
spec:
clusterIP: None
selector:
app: grpc-receiver
ports:
- name: 'grpc'
port: 6565
protocol: 'TCP'
targetPort: 6565
但是,当我尝试从 grpc-sender 向 grpc-receiver 发送消息时,我只是在 grpc-sender 日志中看到了这个异常:
2021-01-08 17:46:24.494 ERROR 1 --- [ault-executor-0] io.grpc.internal.ManagedChannelImpl : [Channel<1>: (grpc-receiver:6565)] Uncaught exception in the SynchronizationContext. Panic!
java.lang.NoSuchFieldError: NAME_RESOLVER_SERVICE_CONFIG
at io.grpc.services.HealthCheckingLoadBalancerFactory$HealthCheckingLoadBalancer.handleResolvedAddresses(HealthCheckingLoadBalancerFactory.java:186) ~[grpc-services-1.25.0.jar!/:1.25.0]
at io.grpc.internal.AutoConfiguredLoadBalancerFactory$AutoConfiguredLoadBalancer.tryHandleResolvedAddresses(AutoConfiguredLoadBalancerFactory.java:154) ~[grpc-core-1.34.1.jar!/:1.34.1]
at io.grpc.internal.ManagedChannelImpl$NameResolverListener$1NamesResolved.run(ManagedChannelImpl.java:1668) ~[grpc-core-1.34.1.jar!/:1.34.1]
at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:95) ~[grpc-api-1.34.1.jar!/:1.34.1]
at io.grpc.SynchronizationContext.execute(SynchronizationContext.java:127) ~[grpc-api-1.34.1.jar!/:1.34.1]
at io.grpc.internal.ManagedChannelImpl$NameResolverListener.onResult(ManagedChannelImpl.java:1682) ~[grpc-core-1.34.1.jar!/:1.34.1]
at io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolver.java:333) ~[grpc-core-1.34.1.jar!/:1.34.1]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na
谁能给我任何关于我做错了什么或我错过了什么的指示?
顺便说一句 - 我知道使用 GRPC 进行负载平衡的替代方法,例如使用 Linkerd 或 Istio 等服务网格或仅使用 Envoy 代理,但我热衷于使用 GRPC 的开箱即用负载平衡功能来工作不同方法之间的比较点。
非常感谢!
我发现了您的代码的一些问题:
forTarget
而不是forAddress
像dns:///grpc-receiver:6565
,因为 kubernetes 服务路由 dns 有多个实例,请尝试解析这个名称。NoSuchFieldError: NAME_RESOLVER_SERVICE_CONFIG
是由 lib 不匹配引起的,grpc-services 版本是1.25.0
,而 grpc-core 版本是1.34.1
,所以将它们设置为相同版本,应该可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.