http2为什么需要流控

最近在思考一个问题,http2协议中的流控和tcp协议的流控是否有关系,是否是多余的,分别是应对什么场景的问题?

tcp的流控是连接级别,不同连接是共享网络,网络中大部分都是非直连的情况,中介的数据buf和转发能力不统一,所以窗口大小只在最近的endpoints之间互通,这样会一段一段的共享窗口大小。两点之间网络的能力通过bdp衡量,该能力不提升硬件能力的情况下是有理论最大值的,tcp的流控就是防止单连接无估计的向网络中写入大量数据导致网络拥塞和丢包,endpoints通信延迟上升,用户无法容忍的情况下就视为网络不可用。那么tcp的流控是怎么做的呢,首先窗口有默认大小,应用层不需要关心,类似64k这种,随着bdp的进一步探测,窗口会有调整,bdp探测模块认为当前连接可以占用更多带宽资源,那么就调整窗口大小,当然窗口大小的调整还依赖于上层读取tcp buffer中数据的效率,如果读取很快证明tcp buffer的写入速度可能成为app处理的瓶颈,那么tcp就会扩大窗口,向sender索要更多数据。

http1.1是一段时间内(一个rtt)独占tcp连接的,相当于一个请求就占用所有连接的资源,包括本地buffer以及tcp连接级别流控涉及到的窗口大小等限制。这种1v1的对应关系所以依托于tcp连接的流控就行,你自己设置流控也没意义。不过tcp连接是多个请求共用的,请求传递的数据大小不一致,对于tcp连接的占用时间也不一致,请求大小的波动会干扰到连接窗口的调整效率,大请求体独占连接时更可能让tcp达到理想效率,会让窗口更快达到设计的理论值。

http2的单tcp连接是多个stream共用,tcp连接单位时间内能处理的byte数量有限(依赖于bdp,窗口调节,网络状况,中介是否有瓶颈),网络连接之于tcp连接,应该就像tcp连接之于http2,抽象的来看,共享资源就需要上层各使用方克制自己,从小的窗口大小开始根据bdp的预估来看是否能调大窗口。防止tcp连接被长时间独占。grpc-go中的单连接利用单goroutine处理所有写到tcp连接的任务,这些任务区分stream存储在map中,每个stream被处理完成后,会放到队伍尾部,为了公平。

grpc-go中流控的处理到底是不是高效的?就看是不是单连接单goroutine的情况下,能不能打满带宽,各stream堆积的任务有多少?这块有必要进行细致的基准测试。

http2为什么需要流控
Share this