grpc-go性能优化(一)

HandleStreams是所有frame的入口,grpc-go当前处理的frame类型分为6种,下面分类型讨论下怎么让frame中的互相干扰逻辑并发起来。 MetaHeadersFrame 请求的第一个frame,第一步是解析header中的内容,解析过程耗时固定,不能分离到goroutine中,但是当解析出错,就用到controlbuf,这里是第一个点,这里给到controlbuf的是一个cleanupStream,loopyWriter这个对外接口人负责处理,就是向外发一个RST_STREAM,receiver端还要从transport全局的map中摘除这个frame,这一个put操作还是会收到loopyWriter的干扰,但本身两者可以尽量没有关系,这个点一定是不被允许的,虽然出现的几率很小,但是大型高并发线上服务一旦出现波动是很难重现和调试的。cleanupStream是异步被处理,虽然尽快处理是理想的,这时候就要在几种方法下tradeoff: rst操作保留在read流程,rst操作是要通过conn的Write写出,这里存在竞争,这块依赖于response的写出竞争程度,不可靠 rst操作通过lock-free queue分离,最终在loopyWriter中发出 rst操作通过wait-free

  • themonk
6 min read

grpc-go中controlbuf是否是性能瓶颈

之前一直在关注grpc-go性能问题,之所以说是问题,高并发I/O的情况下,read和write都会有ms级别的耗时波动。 被http2协议的流控是否干扰性能这个问题困扰很久,因为grpc-go是我唯一阅读的rpc框架,没有参考,所以对于rpc框架该怎么设计合理,心中没有标准,也没办法衡量。我们之前使用的brpc,性能表现相当好,cpu吃的也不紧,而且github上的文档干活比较多,当然干活多不代表文档全,brpc这方面还是要优化下。所以反复读了brpc在io部分的设计,总结下框架处理高并发I/O要做些什么: 流水线:不同类工作分开处理,防止干扰,针对不同req处理耗时波动大或者不可预估的环节一定要加入并发能力(例如执行用户逻辑的部分,这块通常没有框架会犯低级错误,让用户的业务逻辑互相干扰) lock-free和wait-free:涉及到连接r和w,如果是http2还涉及到frame的顺序保证,所以在框架层内部一定要做到其中一种,最好是wait-free,就是线程之间完全不干扰,

  • themonk
2 min read