V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vevlins
V2EX  ›  前端开发

http2 多路复用的实现原理

  •  
  •   vevlins · 2018-08-14 09:29:22 +08:00 · 5013 次点击
    这是一个创建于 2330 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看到一篇文章,基本的说法的 1.x 需要按照顺序,但是 2 使用了 stream。

    2)所谓请求阻塞意思就是一条 TCP 的 connection 在同一时间只能允许一个请求经过,这样假如后续请求想要复用这个链接就必须等到前一个完成才行。 3 )之所以有这个问题就是因为 HTTP1.x 需要每条请求都是可是识别,按顺序发送,否则 server 就无法判断该相应哪个具体的请求。

    但是 1.x 的请求不可以识别吗?不是有 http 请求头可以对应吗? 还是说同一类型请求的多次发送?

    13 条回复    2018-08-14 18:06:32 +08:00
    rrfeng
        1
    rrfeng  
       2018-08-14 09:36:28 +08:00 via Android   ❤️ 1
    我同样的请求连续发两次,你知道哪个是哪个吗?
    snail1988
        2
    snail1988  
       2018-08-14 09:38:07 +08:00   ❤️ 1
    1.x 的数据流顺序和完整性是直接基于 TCP 的
    2 的数据流是在 TCP 的里面又加了一层 mux 的结构 Stream,一条 TCP 连接可以同时传输多个 Stream

    可以看看 http2 的标准文档,再找个 http2 的实现源码
    zhujinliang
        3
    zhujinliang  
       2018-08-14 09:41:16 +08:00 via iPhone   ❤️ 1
    HTTP1 想要复用链接,必须指定 Content-Length,或者使用 Chunked 编码,否则不能知道什么时候一次请求结束,只能靠断开 TCP 链接结束一次请求
    zpf124
        4
    zpf124  
       2018-08-14 09:45:43 +08:00   ❤️ 1
    http 1.0 应该完全没 这些问题,因为他 tcp 链路都不复用。一个 tcp 三次握手发一个请求就断开了。如果都用 1.0 的协议,人多了服务器就要炸了。

    假设 在 http 1.1 下 出现了同时发多个请求的情况, 我觉得会出问题的不是服务端,而是客户端。

    比如 client 请求了 /api/user 不等返回响应,立马发送新的请求 /api/top,
    这里确实可以做到 服务可以识别到不同的请求,

    但如果 top 的结果先一步算出来,要不要返回?返回了的话 client 怎么判断 当前返回的数据时 user 的还是 top 的?
    nfroot
        5
    nfroot  
       2018-08-14 10:40:26 +08:00   ❤️ 1
    现在能做的事情大部分以前都能做到,但是前提是要想得到,用得上才实际。

    就好像人类的祖先,最重要的是活下来,才有空去研究和改进,然后一步步改进,你让他一次性考虑完全、完整,那早都饿死了。

    协议一定下来,就很久都不会去改变了,要不然别人没法用的。
    est
        6
    est  
       2018-08-14 10:46:57 +08:00   ❤️ 1
    http/1.1 其实有 pipeline 特性,不过大家都不怎么支持。支持了的都说是用来跑分作弊的。

    不过就算 pipeline,也得严格讲究顺序。还是会有 head of line blocking。
    imn1
        7
    imn1  
       2018-08-14 10:55:53 +08:00   ❤️ 1
    我以前 python 写过 http1.1 一个 connection 多次请求的 socket(client),爬虫用
    请求和得到应答部分是成功的,但水平不够,搞不定容错部分,放弃了
    gamexg
        8
    gamexg  
       2018-08-14 11:36:24 +08:00   ❤️ 1
    楼上说的差不多了。

    http1.1 支持的是顺序流,即客户端连续发出多个 http 请求,服务器按顺序处理,处理完第一个就发送第一个的回应,然后处理第二个并发送第二个的回应。缺陷是如果第一个请求响应延迟很大,例如是个长连接推送,那么之后的请求就别想等到回应了,所以实际浏览器并没有用这个功能。
    http2 的是将单个 tcp 连接拆分成多个流,并发的多个请求分别通过不同的流发出及接收,即使中间某个请求时长连接也不会出现什么问题,他只会阻塞自己所在的流,其他请求一样可以正常返回。
    gamexg
        9
    gamexg  
       2018-08-14 11:39:01 +08:00   ❤️ 1
    @gamexg #8 另外补充下,靠谱的 http 服务器如果实现 http 协议正确,能够分清楚每个 http 请求,那么默认就应该是支持 http1.1 pipeline 的。
    est
        10
    est  
       2018-08-14 12:00:21 +08:00
    @gamexg 其实不支持。。想一想各种负载均衡反向代理。。。请求跑到哪一台服务器去了鬼才知道。。。
    gamexg
        11
    gamexg  
       2018-08-14 13:49:42 +08:00
    @est #10 实际前端负载均衡按标准实现 http 协议就没问题。他只管读取请求,转发到后端,获得后端响应,转发响应给浏览器。
    读取 http 请求时只要可靠的实现了 http 协议,那么应该只读取了第一个请求,剩下的请求的还在缓存区,下个循环时才会读取到。
    当然我也见过非常烂的代码,读完第一个请求后不管缓存区是不是还有数据就直接丢弃了...
    est
        12
    est  
       2018-08-14 14:09:18 +08:00
    @gamexg 我觉得有问题。LVS 转发是 4 层基于 tcp 的。。。顺序早就不知道飞到哪个节点去了。。。

    节点自己处理完了自己就返回,压根不会管顺序。。
    gamexg
        13
    gamexg  
       2018-08-14 18:06:32 +08:00
    @est #12 没用过 lvs,以前看过说明,印象 lvs 是浏览器到服务器的部分经过 lvs,服务器到浏览器的部分不经过 lvs。
    这种情况 lvs 负载均衡应该无法拆分单个 tcp 连接到多个服务器,所以对后面的服务器基本等于透明的,还是只看后面的 web 服务器是否支持即可。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1579 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:44 · PVG 00:44 · LAX 08:44 · JFK 11:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.