QUIC 协议基于 UDP, UDP 不可靠, QUIC 如何保证可靠性的呢 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lrs
V2EX    问与答

QUIC 协议基于 UDP, UDP 不可靠, QUIC 如何保证可靠性的呢

  •  1
     a href="Javascript:" Onclick="downVoteTopic(777845);" class="vote">
  •   lrs 2021-05-19 10:40:14 +08:00 6793 次点击
    这是一个创建于 1656 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近写代码练手,写一个网络发送文件的小程序,可选 TCP 或 UDP 为传输方案。写到 UDP 传输方案的时候发现丢包检测重传之类的逻辑越写越乱越写越复杂,于是准备看下 QUIC 怎么实现的。翻了翻 QUIC 的 RFC 文档,看的我头大。
    比较好奇的是,既然 UDP 会丢包,包含传输控制信息的包也是会丢的。控制信息要是丢了,岂不就是 hang 在那里了啊。如果采用超时机制来保证控制信息的重传,这效率(传输速度)就没法保证了。
    所以,QUIC 是如何做的呢
    31 条回复    2021-05-20 11:09:09 +08:00
    binux
        1
    binux  
       2021-05-19 10:44:18 +08:00 via Android
    你知道 TCP 是如何保证可靠性的吗?
    Overfill3641
        2
    Overfill3641  
       2021-05-19 11:09:21 +08:00
    QUIC 好像有类似 RAID5 的校验机制,会多发一些包以用于修复,而且会根据丢包率多发多少包的。非专业人士只是看过介绍。
    chenset
        3
    chenset  
       2021-05-19 11:18:41 +08:00
    也是类似 TCP 的 ack 机制, 不过 TCP 是网卡硬件实现的,几乎不消耗 CPU. QUIC 目前是软件实现的, CPU 性能消耗非常大.
    sujin190
        4
    sujin190  
       2021-05-19 11:27:37 +08:00   3
    tcp 的重传流控都已经搞了无数 paper 了,基础逻辑肯定是用超时、数据包到达顺序来做的,但是怎么做就不是一两句话说得清了,QUIC 用的还是这些重传流控方案,比如 CUBIC 或是 BBR,区别就是 QUIC 用户 http 这种短小数据量的可以不使用慢速开始,在现在网络较 http 请求传输量来说普遍十分高了,取消慢速开始可以显著提高初始传输速度和延迟

    而且流控方案被实现在了用户空间,那么你也可以依据请求的类型啥的选择或动态改变重传流控方式,比如可以给视频使用抗拥塞但是网页请求用低延时的重传流控方案,也可以在请求时协商使用啥重传流控方案,tcp 的重传流控被实现的内核,通过内核参数控制,完全不可控啊也是坑死人
    nicebird
        5
    nicebird  
       2021-05-19 11:42:00 +08:00
    重新实现一套 tcp 机制
    shyling
        6
    shyling  
       2021-05-19 11:43:35 +08:00
    重新实现 tcp
    ch2
        7
    ch2  
       2021-05-19 11:49:30 +08:00   1
    "如果采用超时机制来保证控制信息的重传,这效率(传输速度)就没法保证了"
    要不然你以为为什么网络不好的时候 tcp 下载文件会掉速?
    PeakFish
        8
    PeakFish  
       2021-05-19 12:01:05 +08:00
    谁告诉你 udp 不可靠了
    raaaaaar
        9
    raaaaaar  
       2021-05-19 12:09:34 +08:00 via Android
    des
        10
    des  
       2021-05-19 12:10:51 +08:00 via iPhone
    @chenset 没听说过网卡还干这活
    raaaaaar
        11
    raaaaaar  
       2021-05-19 12:11:29 +08:00 via Android
    TCP 就是用不可靠的底层协议,来实现可靠传输的
    lrs
        12
    lrs  
    OP
       2021-05-19 12:12:14 +08:00
    @binux 具体不是很了解。

    @v2tudnew 哦,就是冗余啊。感觉是在碰运气,因为不知道哪个会丢。

    @chenset
    @nicebird
    好的(笑哭) 这回复言简意赅,一下就看懂了。

    @sujin190 感谢花费篇幅解释。慢速开始是指 TCP 开始的几次握手吗?所以重点是流控方案,感觉要弄明白得花时间了。

    @ch2 明白了。细想之后我有了一个新疑问:正常网络里,如果忽略硬件产生的问题和人为的因素(比如 QOS ),是什么引起的丢包呢,也就是不可靠的源头是什么?
    ch2
        13
    ch2  
       2021-05-19 12:19:37 +08:00
    @lrs #12 就跟送快递一样,路上中间某一个路由器某一时刻需要发的包实在太多了,堵在上面来不及发出去,超时了。更深层次的原因是,网络拥堵情况是动态的,不能使用固定的发包速率,所以发包的人需要试探一个理论上的发送速率最大值
    zengming00
        14
    zengming00  
       2021-05-19 12:20:48 +08:00
    貌似单个包的大小如果小于 MTU 值还是比较可靠的
    Overfill3641
        15
    Overfill3641  
       2021-05-19 12:22:23 +08:00
    确实属于碰运气,谷歌的意思应该是减少延迟、额外开销之类的,然后加上校验降低重传率(这样就不用等超时了),我个外人感觉还是可以的,如果对 UDP 和 TCP 都一样 QOS 公正的话。
    caola
        16
    caola  
       2021-05-19 12:28:26 +08:00
    @lrs 现在 http/3 很快就要正式发布了,
    nginx 目前可以通过其官方的 h3 补丁来增加支持,go 语言有 quic-go 包
    至于如何实现的,建议你可以去查看源代码

    QUIC 以后会慢慢取代 TCP 的地位
    Tianao
        17
    Tianao  
       2021-05-19 12:29:43 +08:00 via iPhone
    TCP 协议基于 IP,IP 不可靠,TCP 如何保证可靠性的呢
    sujin190
        18
    sujin190  
       2021-05-19 14:20:01 +08:00   1
    @lrs #12 并不是,满开始是 tcp 连接不知道网络有多少带宽可用,所以握手成功后,先发几个包,成功受到确认没有丢包才会慢慢增加发包数量,通俗点就是连接探测可用带宽的过程,现在宽带、4g 、5g 带宽都很大,对于 http 这种大多数情况下不会发送大量数据造成持久性网络拥塞的,已经没啥必要做慢开始过程了
    robot1
        19
    robot1  
       2021-05-19 14:26:46 +08:00
    看 kcp 文档
    GuuJiang
        20
    GuuJiang  
       2021-05-19 16:31:21 +08:00 via iPhone
    @PeakFish ???
    jim9606
        21
    jim9606  
       2021-05-19 17:02:21 +08:00/span>
    如果你只是搞上层应用,别自己写,直接搬别人的实现就是了。
    ( https://github.com/lucas-clemente/quic-go )

    真要深入研究这个你得先把 TCP 的设计搞清楚,这玩意往大的说,能写一本厚书了。
    wellsc
        22
    wellsc  
       2021-05-19 18:06:29 +08:00
    64 位 id + 重传
    tiddarabbit
        23
    tiddarabbit  
       2021-05-19 20:21:26 +08:00
    @chenset "TCP 是网卡硬件实现的,几乎不消耗 CPU"
    love4taylor
        24
    love4taylor  
    PRO
       2021-05-19 21:00:20 +08:00 via iPhone
    @des 他说的应该是 TCP 卸载
    msaionyc
        25
    msaionyc  
       2021-05-19 21:10:38 +08:00 via iPhone
    @PeakFish UDP 可靠吗
    joyqi
        26
    joyqi  
       2021-05-19 21:12:55 +08:00
    质不够量来凑
    chenset
        27
    chenset  
       2021-05-19 21:42:15 +08:00
    #3 严重错误, 请忽略
    ysc3839
        28
    ysc3839  
       2021-05-19 23:07:01 +08:00 via Android
    你是想自己实现一个 UDP 可靠传输协议吗?
    还是说只是希望自己写的小程序走 UDP 传输的同时保证可靠?
    如果是后者,建议使用 KCP 之类现成的协议。
    msg7086
        29
    msg7086  
       2021-05-20 05:09:04 +08:00   1
    @lrs #12 丢包的本源就是缓冲区满了。(这个在计算机网络课程里应该有讲到。)
    #13 的快递比喻基本是正确的,但是丢包一般是因为缓冲区满了。
    缓冲区就相当于快递集散点的仓库,短时间内快递多,可以先堆着慢慢送,但是如果遇到过节大甩卖,快递多到仓库都堆不下了,爆仓了,那么对于硬件设备来说就是直接丢弃掉了。
    因为丢弃的包不会有回传消息,所以在软件这边看来就是等待直到超时。
    因为超时对发送流量的影响更大,所以一般的流控会选择主动减速,空出缓冲区,保证发出去的包都不会因为爆仓而丢弃。但是这个减速的机制则需要微调个几十年。
    wanguorui123
        30
    wanguorui123  
       2021-05-20 07:29:31 +08:00 via iPhone
    纠错算法了解下
    lrs
        31
    lrs  
    OP
       2021-05-20 11:09:09 +08:00
    @PeakFish #8 我是在网上看的好多地方描述 UDP 的时候都写 unreliable

    @shyling #6
    @raaaaaar #11
    @v2tudnew #15
    @robot1 #19
    @jim9606 #21
    @wellsc #22
    @wanguorui123 #30
    好的,多谢指点

    @ch2 #13
    @sujin190 #18
    @msg7086 #29
    明白了,感谢解释

    @zengming00 #14 一般都是小于 MTU 的吧

    @caola #16 嗯,已经找了 quinn 的代码在看

    @Tianao #17 哈哈哈,不要这样造句啦

    @joyqi #26 嗯,然后凑也是有讲究

    @ysc3839 #28 只是写着玩儿,后来发现 UDP 做可靠性挺复杂,自己实现一个感觉不大现实,还没那么强做不到呐。多谢指点,我去找下 KCP 文档看看
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2536 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 04:11 PVG 12:11 LAX 20:11 JFK 23:11
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86