grpc c++使用以及踩坑

两个因素想做开源项目:

1 主导开发中间件系统的心愿已经达成,虽然中间磕磕碰碰的踩了很多坑。

但毕竟最终结果是好的。

唯一的遗憾就是没有开源了。

2 之前做了一些小网站,也累积了不少用户,但是对技术的磨练还是太少了。

特别是用户的增长出现瓶颈以后,架构和细节已经没有必要在优化了。这就让人产生了惰性。

认真做一个开源项目,会有bug issue和功能的issue。会有人去推动你不断探究。

我认为这会收获巨大。

具体项目没想好,可能是基础库(偏网络高并发?又一个轮子?),也可能是比较擅长的存储系统。

做存储系统的话,会比较慎重,毕竟会是以十年计的项目(参考fastdfs的余庆前辈)。

不管是参考着做一些开源库,还是做存储系统。

调研(研究透彻了有问题才自己轮)或者做存储系统使用一个开源rpc框架(总不能拿公司框架出来做开源项目吧)都是必须的。

本文就以探究grpc框架为主,基于1.12版本

安装使用

最简单的是使用vcpkg安装静态库,不推荐这么做。

实测grpc的静态库会有很大的性能损耗,比起后来自己编译的动态库有75%的性能损耗,暂时还不清楚原因。

1
2
3
4
5
6
7
8
9
10
11
sudo apt-get install build-essential autoconf libtool libgflags-dev libgtest-dev clang libc++-dev pkg-config unzip
git clone -b $(curl -L http://grpc.io/release) https://github.com/grpc/grpc
cd grpc
git submodule update --init
make
sudo make install
cd third_party/protobuf
sudo ./autogen.sh
sudo ./configure
make
sudo make install

以上安装过程是从别的博客复制过来的,centos的环境应该会有些差别。我自己的centos环境是全的,直接可以安装。

安装以后cmake写上如下

1
2
3
target_link_libraries(${TARGET} protobuf)
target_link_libraries(${TARGET} grpc)
target_link_libraries(${TARGET} grpc++)

可以把grpc的example复制过来编译试试看。

也可以直接跑我这个项目的build脚本

grpc_test

里面有同步,异步,多线程异步客户端的demo。

使用

同步客户端没什么好说的,内部实现是一个线程池,性能上会有很大问题(线程争用)。

异步客户端必须严格按照以下流程(任何一阶段乱序都会core掉我试过啦)

1
2
3
4
5
6
7
8
9
RegisterService
cq = AddCompletionQueue
BuildAndStart
//This can be run in multiple threads if needed.
while (1) {
new CallData(..., serviceType, apiType)
cq->Next(&tag, &ok)
static_cast<CallData*>(tag)->Proceed();
}

如果想要调用不同的service(指proto),或者不同handler(指相同proto下的不同handler)

需要在CallData进行封装,每个CallData会是grpc事件循环的调度单位

测试

这是坑爹的部分

测试还是使用我上面提供的github项目,使用go客户端进行压测

动态编译的1.12性能比静态的好得多了,但还是不佳,主要体现在网络10%负荷的情况下,cpu只能跑一半。

以为是自己的问题,在ubuntu和centos上都装了好几次,依然没法。

这个时候只能怀疑是grpc的问题了。

我直觉上grpc可能是锁争用了,上gperf一测果然是这样,wait和signal是最高消耗。

去翻了一下issue果然是这样。

Poor c++ performance benchmark result

gprc官方测试

即使是官方自己的测试,c++的性能也只有java的一半,8核还能跑一大半,32核只能跑三分之一了

很明显的锁争用阿。

不太清楚grpc的团队是不是很忙,这个issue提出来2个月了,在10天前才被定为bug

于是我换版本,一直换到1.6,依然是这个问题。

issue说1.6是java性能两倍,我没感觉到有性能提升。也看不到官方图表关于以前版本的数据。

grpc的这一次探究暂时算是扑街

待续

grpc的go版本很棒,可能主要还是依赖了go良好的协程模型,一般写不出什么性能问题来。

c++版本更像一个玩具,可能还是研发人员的精力不够吧,毕竟不是全职。

等c++版本修复了这个问题再来跟进吧。

PS:每个网络库都自称自己很牛,实际的库用户更像是抽奖,赌对了起飞,错了血崩。

怪不得现在层出不穷的各种轮子,至少有问题自己能方便改啊。

看来再轮一个开源网络库也不是不可以。