go grpc域名不重解析问题
背景项目使用k8s + go-grpc, A服务作为客户端需要通过grpc连接B服务, B服务是通过k8s的service的nodeport方式暴露的。协议用的是dns协议,resolver用的是go-grpc自带的dns-resolver。现象删除B服务的pod发现A服务能正常感知到,如果B服务的pod所在节点重启发现A服务并不能感知到,还是会让请求路由到宕机的pod上面。排查发现项目用的sch
背景
项目使用k8s + go-grpc, A服务作为客户端需要通过grpc连接B服务, B服务是通过k8s的service的nodeport方式暴露的。
协议用的是dns协议,resolver用的是go-grpc自带的dns-resolver。
现象
删除B服务的pod发现A服务能正常感知到,如果B服务的pod所在节点重启发现A服务并不能感知到,还是会让请求路由到宕机的pod上面。
排查
发现项目用的schema是dns,用的是grpc自带的dns_resolver。
grpc客户端连接过程:
grpc.DialContext 建立连接,返回clientconn
getResolver(clientconn.go) 通过传入的scheme返回对应的解析器
newCCResolverWrapper(resolver_conn_wrapper.go) 构建对应的解析器
调用builder提供的build方法
grpc 自定义的dns_resolver.go的build方法
启动一个watcher协程
watcher里面具体动作如下:
通过一个rn的channel接受信号,接收到rn的信号后调用lookup方法重新解析域名,解析完成后更新clientconn里面的连接状态。
调用ResolveNow方法(真正的解析域名的动作)
这里会发现grpc正常情况下可能一直都不会重新解析域名,看起来这里是一个不太合理的方式,看代码提交,19年11月之前的代码dns是会每隔30分钟重新解析一次,找到当时的提交记录如下https://github.com/grpc/grpc-go/pull/3228,而且发现里面关于dns重新解析的issue,这个issue当前仍然是处于open状态的https://github.com/grpc/grpc/issues/12295 。
解决方案
自定义dns_resolver替换到grpc自带的dnsresolver,build方法里面每隔10s进行一次域名的重解析。
更多推荐
所有评论(0)