go sync.pool []byte导致grpc解包异常

前言:

在使用golang sync.pool的时候遇到一个小坑,这个小坑会导致我们grpc网关的反序列化失败。是什么原因导致的? 😅

该文章后续仍在不断的更新修改中, 请移步到原文地址 http://xiaorui.cc/?p=5969

问题:

简单说,没有清理以前的数据引起的。以往对于socket server和grpc server的拆包解包是用 bytes.Buffer,在每次使用完sync.pool put的时候,会及时的该对象进行reset重置。但这次用了[]byte,需要手动实现[]byte的length重置。

[]byte是个字节切片,他对应的sliceHeader底层是有三个字段,len、cap、data 。 data 是一个数组,cap是数组的大小,len是实际存储数据的大小。那么重置其实操作 len = 0就可以了。但因为len字段是小写不可见,上层无法进行操作。

看了下bytes.Buffer的reset重置代码,他是通过 obj[:0] 引用的方法来重置len大小的。

下面是我这边修改后的sync.pool []byte应用代码,大家可以参考下。

总结:

grpc gateway在使用sync.pool缓冲[]byte后,gc的延迟有锁下降。另外,编译的golang版本需要注意下。在1.12.x版之后。sync.pool增长了对象存活周期,规避因为gc清理后,造成的各类竞争,大概延长了两个gc左右。
在go 1.13的版本里,sync.pool又优化了锁竞争的问题,性能方面值得期待。

注意: 在调试grpc网关时,发现一个性能优化点。在grpc里加入连接池,grpc的吞吐方面性能是有提升的,因为虽然grpc基于http2是可以多路复用,但问题http2也是存在tcp协议层的对头阻塞。另外,golang的net/http实现的http2存在各种的锁竞争。对的,还是锁。


对Golang感兴趣的朋友可以加群: 278517979 !!!
另外如果大家觉得文章对你有些作用! 如果想赏钱,可以用微信扫描下面的二维码, 感谢!
另外再次标注博客原地址  xiaorui.cc