JAVA grpc客户端在k8s环境下使用dns负载均衡遇到的问题

那尔撒斯 962 2021-11-23

0x01 问题来源

之前公司业务层调用平台接口使用的是http请求的接口,没有遇到过负载均衡的问题,刚好我的这个项目因为要传大图,为了性能,选择直接走grpc协议来提供服务。开始一切都很顺利,测了很久都没有啥问题,今天开始测性能,本以为一切会跟往常一样索然无味(手动狗头),结果不一会儿测试小哥就看出问题了。。。业务所有的请求都打到同一个pod上了-_-!k8s负载均衡没起效果!
检查了一遍k8s,没看出啥异常,service也是headless的(clusterip为None),在pod里面telnet测试连服务也能连上,oTL,麻了,究竟是哪儿不对?经大佬提醒,"grpc是长连接",我赶紧一波搜索,果然这里面有门道。

0x02 第一次尝试

看了很多文章,提到grpc的负载均衡需要走客户端方式,当然也有一些比较复杂的方案,不过为了最小化改动项目,目前只能走dns负载均衡的方式。先在pod里面测试ping了一下,dns能自动切换。然后让业务同学在java那边在k8s内部域名前面加上了"dns:///",这次一定可以了吧?然并卵。。。

0x03 第二次尝试

还有哪儿没对??找java同学debug进去检查了传入的url也没问题,网上搜了很久,也没有更多资料。。。一度陷入僵局。于是,我决定换个方向搜索,grpc能够搜到的最多的文章还是集中在go的上面,咱先看看go是怎么连的!实在不行,我可以自己用go写个客户端自己做实验。然后。。。在go的文章里面找到了端倪,除了加上"dns:///"协议头以外,一般还要设置负载均衡策略,比如设置为交替进行(round robin)。让java同学看了一下,确实有这个设置项,立马改了走一波。果然!两个pod负载都上去了。。。

经验:

可以多参考一下各种语言的实现版本,说不定也能得到一些启发