grpc-go请求ingress遇到的一个问题

背景&现状:

公司有两个内部微服务A、B,A->B 使用 grpc-go 客户端负载均衡策略,即:consul + round_robin。随着业务的增长,B服务的服务器资源数量一直在增加,有个问题:在一天24小时的时间里,有大概1/3的时间没有业务,就造成了服务资源的浪费。

为了减少资源浪费,决定动态的对B服务扩缩容,最终决定使用K8S管理。
这样的话,就需要在K8S管理的B服务前面增加一个网关,公司采用的是ingress。

问题:

在增加了ingress+K8S之后,A服务请求ingress进行验证时发现:请求ingress服务一直不成功,但是使用grpcurl工具测试却是成功的。

ingress失败显示的日志 "PRI * HTTP/2.0" 400 错误

1
2
// Not working...
conn, err = grpc.Dial("test-b.com:443", grpc.WithInsecure())

由于在请求时,没有使用证书,所以在调用Dial() 方法时,使用了 grpc.WithInsecure()。

1
2
# working...
./grpcurl -insecure -d '{}' test-b.com:443 b.Servers/GetData

grpcurl 使用 -insecure 标识不使用证书

思考

针对这个问题,抛出几个问题
1.公司A服务、grpcurl都使用的grpc-go进行开发的,并且版本一样。排除grpc-go版本不一致造成的问题
2.在使用grpcurl时也没有使用证书,但是grpcurl却成功,公司A服务却失败。这里面应该就是发生错误的根源所在

基于以上两个问题,追溯了一下grpcurl的源码

解决方案

追查grpcurl的代码,发现

1
2
3
4
5
6
// Working...
var tlsConf tls.Config
tlsConf.InsecureSkipVerify = true

var creds = credentials.NewTLS(&tlsConf)
conn, err = grpc.Dial(host, grpc.WithTransportCredentials(creds))

使用 grpc.WithTransportCredentials(creds) 代替 grpc.WithInsecure() 即可。

至于具体原因,可以追溯 grpc-go 源码