问题描述
我有一个grpc客户端,指向一个解析为2个IP地址的URL。 问题是,当一个服务器节点发生故障然后又恢复时,grpc客户端不会选择它,而所有负载都转移到单个节点上。
我尝试过推荐以更改networkaddress.cache.ttl
的属性,但这没有帮助。
我的代码(在Scala中)
java.security.Security.setProperty("networkaddress.cache.ttl","30")
System.setProperty("networkaddress.cache.ttl","30")
val channel = NettyChannelBuilder.forAddress(host,port).nameResolverFactory(
new DnsNameResolverProvider).usePlaintext().build
val client = MyServiceGrpc.newStub(channel)
grpc版本:1.32.1
解决方法
假设DNS一直都返回两个IP(可能被改组),那么问题就出在DNS缓存上。问题在于gRPC的连接正常,因此不会选择重新连接并且不会执行DNS查询。
您应该使用MAX_CONNECTION_AGE
配置服务器,以强制客户端偶尔重新连接以重新平衡负载。当客户端与服务器断开连接时,它们会触发新的DNS解析,因此也可以用来查找新地址(尽管重新连接不会等待DNS解析完成)。
在Java中,MAX_CONNECTION_AGE
可通过NettyServerBuilder.maxConnectionAge()
使用:
NettyServerBuilder.forPort(yourPort)
.maxConnectionAge(30,TimeUnit.MINUTES)
....
您希望使用可以接受的最大年龄。在30分钟左右的时间内,每个客户将每30分钟重新平衡一次。因此,在服务器重新启动15分钟后,该服务器将承担1/4的负载,而在30分钟后,它将承担大约1/2的负载。
,似乎可以配置负载平衡策略来完成这项工作:
NettyChannelBuilder.forAddress(host,port).defaultLoadBalancingPolicy("round_robin").usePlaintext().build()