请教大佬们一个问题,hyper http1 client写数据时通过一个BufList写内部的buffer结构是[Bytes],然后写到网络中是调用的writev,但是在http2的实现里这个buffer是BytesMut,写数据时都是先把数据拷贝到这个BytesMut里,为什么不像http1一样去写到Buflist里呢?
1
共 1 条评论, 1 页
请教大佬们一个问题,hyper http1 client写数据时通过一个BufList写内部的buffer结构是[Bytes],然后写到网络中是调用的writev,但是在http2的实现里这个buffer是BytesMut,写数据时都是先把数据拷贝到这个BytesMut里,为什么不像http1一样去写到Buflist里呢?
评论区
写评论http1是一个tcp连接,同一时刻只能跑一个http request/response,即便是鲜有使用的pipeline模式也是如此,因此客户端/服务端写入http实体时,可直达tcp,由tcp交给协议栈发送,因此可以用BufList,BufList可以使用writev发送提高效率。
但http2就不一样了,http2是多路复用,一个tcp连接可以处理多个http request/response,写入一个http request,就不能直达tcp直接发送了,因为多个http request,它们要公平发送。反过来举个例子,如果http2下,一个http request要上传10GB内容,要把这10G内容全写入tcp上优先发送,那10GB可不是小数目,这条tcp连接上的其它http2 request得相当长一段时间被“饿死”,这样显然不行,因此,http2的每个请求先写入到一个BytesMut,再由http2 “公平”地从各个存活的请求的BytesMut中读取相等的部分数据发送,达到“公平”、“并行”处理各个请求的效果。
http2的多路复用,至少需要两层缓冲区,http2实体需要一个缓冲区,http2的发送控制又需要一个缓冲区,应用时只能接触到http2实体缓冲区,此时再用BufList意义不大。
hyper能区分http1和http2的方式,为了性能牺牲了api的统一性,体现了遵循零成本抽象的性能优先原则。实际上,它也可以让http1先写入到BytesMut,但这样让http1多了一部分Copy的消耗