添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
// xiaorui.cc
func (cs *clientStream) withRetry(op func(a *csAttempt) error, onSuccess func()) error {
	cs.mu.Lock()
	for {
		if cs.committed {
			cs.mu.Unlock()
			return op(cs.attempt)
		a := cs.attempt
		cs.mu.Unlock()
		err := op(a)
		cs.mu.Lock()
		if a != cs.attempt {
			// We started another attempt already.
			continue
		if err == io.EOF {
			<-a.s.Done()
		if err == nil || (err == io.EOF && a.s.Status().Code() == codes.OK) {
			onSuccess()
			cs.mu.Unlock()
			return err
		if err := cs.retryLocked(err); err != nil {
			cs.mu.Unlock()
			return err

如何grpc client的吞吐问题?

跟解决net/http一个套路,就是增加连接池。我这边写了一个应用在grpc网关的grpc client连接池,可能不适合大家直接去引用,但可以参考下。 https://github.com/rfyiamcool/grpc-client-pool

代码为了规避获取grpc client的锁消耗,所以采用了预先初始化客户端池,为了规避连接泄露,使用lazy加锁初始化连接的方法。简单说,获取client的过程不加锁。。如果有动态扩充连接池的需求,可以使用copy on write map的方法来规避锁map的读写冲突。

单个grpc client的吞吐性能数据,在并发200的时候,client cpu在600%左右,当超过200并发后,cpu会逐渐升到1100%,qps吞吐量反降。

// xiaorui.cc
[root@k8s1 ~]# ./client  -addr=10.2.0.24:50051 -c=1 -n=1000000 -g=50
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 1, worker num: 50
multi client: 1, qps is 68829
[root@k8s1 ~]# ./client  -addr=10.2.0.24:50051 -c=1 -n=1000000 -g=100
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 1, worker num: 100
multi client: 1, qps is 80752
[root@k8s1 ~]# ./client  -addr=10.2.0.24:50051 -c=1 -n=1000000 -g=300
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 1, worker num: 300
multi client: 1, qps is 58041
[root@k8s1 ~]# ./client  -addr=10.2.0.24:50051 -c=1 -n=1000000 -g=500
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 1, worker num: 500
multi client: 1, qps is 54913

多个gprc client的性能表现情况?

// xiaorui.cc
./client  -addr=10.2.0.24:50051 -c=50 -n=1000000 -g=100
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 50, worker num: 100
multi client: 50, qps is 148335
./client  -addr=10.2.0.24:50051 -c=50 -n=1000000 -g=250
server addr: 10.2.0.24:50051, totalCount: 1000000, multi client: 50, worker num: 250
multi client: 50, qps is 217028
./client  -addr=10.2.0.24:50051 -c=100 -n=2000000 -g=1000
server addr: 10.2.0.24:50051, multi client: 100, worker num: 1000
multi client: 100, qps is 359081

在多grpc client的并发下,grpc的吞吐是可以压测到35w的QPS。多个grpc client在提高qps吞吐之外,也能规避单个grpc client在高并发请求场景下产生竞争,竞争会拖慢qps吞吐量。

有朋友可能疑惑了,一个服务实例化这么多连接好么?我们要知道nginx upstream的keepalive连接数过小的化,他的qps是上不去的。使用ab, wrk进行压测时,client数太小照样会影响qps的指标。当然,作为业务服务来说没必要使用连接池,大多数也没这么大的请求量,又因为优秀的架构设计是可以扩展分布式。但作为网关还是有必要的。

由于grpc网关的设计偏复杂,所以我单独写了个我把grpc的测试脚本,已封装成项目放到github了,有兴趣的可以拉下来性能测试。需要注意下软中断及内核日志情况。https://github.com/rfyiamcool/grpc_batch_test

grpc复用http2协议是个好事,这样能让grpc有高度的兼容性,但是相比thrift来说性能是差点意思。毕竟grpc相对于thrift来说,需要unpack两次数据包,一次是header,一次是protobuf body。但话又说回来,相比性能,grpc有更活跃的社区支持和兼容性。

像istio的envoy sidecar本就支持http2,那么自然就很容易支持grpc。而像小米为了解决kubernets istio的联合,改了不少istio的控制面板代码来支持thrift协议。

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