背景
又是一年一度的秋季校招开始了,以往的校招各个公司都会在公司现场或者学校现场安排学生进行现场面试?但是今年由于疫情的原因,不允许让同学在现场进行一个面试,所以今年的面试形式就从线下转到了线上,面试形式的转变,但是我们考核学生的方式依旧没有转变。
校招的同学和社招的同学有很大的不同,他们没有丰富的工作经验,没有太多的项目经历,那么我们如何去衡量一个校招的同学呢?那就是基础和潜力,怎么去理解基础呢?俗话说不积跬步,无以至千里,不积小流,无以成江海,如果没有一个好的基础那么怎么才能成为一个优秀的工程师呢。如何去考察一个学生基础的好坏呢?我觉得有三个方面比较重要,计算机网络,操作系统以及算法和数据结构,通常来说计网考察得特别多,常见的一些问题:
- 网络模型分层
- TCP和UDP的区别
- TCP三次握手和四次挥手
- HTTP各版本的区别
上面列举的问题只是其中一部分,这些问题基本在上课的书本中找到答案,如果你这些都不会那么只能说基础算是比较差了。由于这次是视频面试,我通常会问你觉得牛客网的视频面试是用的TCP还是UDP呢?在我揭晓答案之前大家也可以想想使用的是哪个网络协议,在面试的过程中所有的同学都回答了应该是使用的是UDP。我问为什么使用UDP?基本都会回答道UDP是一个无连接的协议,不用保证可靠性,传输速度快。我又问道如果UDP不保证可靠性,咱们在视频面试的时候我问你问题,如果你回答问题的视频流丢包了,那么你的答案我就听不见了,那视频面试的体验将会非常低。不少同学在这个时候就会改答案说那应该使用的是TCP吧,我这是又会问道TCP由于需要保证可靠性,但是在公网的复杂环境下,想必应该经常会出现缓冲或者卡顿的现象吧,很多同学这个时候就会哑口无言了。
其实这个问题的答案不难想出,我们可以将TCP和UDP的特性互相结合起来,让这个协议既可以保证可靠性,又可以保证实时性,这也就是我们所说的RUDP((Reliable UDP),常见的RUDP协议有QUIC,WebRTC,Aeron等等,我这里主要介绍谷歌提出的QUIC,带大家领略一下RUDP的精彩,看看他们是如何既能做到可靠又能保证效率。
QUIC
QUIC(Quick UDP Internet Connection)是Google公司提出的基于UDP的高效可靠协议,他和HTTP一样同样是应用层协议。
为什么高效呢?是因为其基于无连接的UDP而不是基于TCP去实现的。
为什么可靠呢?因为其模仿TCP协议的可靠性,在应用层上做了可靠性的保证。
为什么需要QUIC?
互联网已经发展了几十年了,但是一提到网络协议,传输层使用得最多的还是TCP协议,应用层使用得最多的是HTTP协议,当然HTTP底层也是使用得TCP协议。虽然互联网已经发展这么久了但是对于TCP来说发展依旧缓慢,要说最大的改进应该是Google 在 ACM CoNEXT
会议上发表的用于改善 Web 应用响应延时TCP Fast Open,通过修改 TCP 协议利用三次握手时进行数据交换,这个在Linux内核 3.7.1 以及更高版本可以支持。由于修改TCP协议必然会修改内核从而导致系统升级,这个推动的难度非常之大。
既然我们修改内核不行,那么Google就提出了在应用层协议上修改的办法,也就有了QUIC。
谁在使用它?
首先使用它的人肯定是谷歌,据说谷歌有50%的请求都是QUIC协议,微博也在全面使用QUIC协议,同时还有一些视频云服务比如七牛也在使用,在腾讯内部也有很多部门在大量使用QUIC,所以不需要担心这个协议使用的问题。
QUIC为什么这么牛?
0RTT 建立链接
RTT((Round-Trip Time)顾名思义就是往返时延的意思,0RTT的话意思就是QUIC可以在第一次发送的时候就带上数据,熟悉我们TCP的同学应该知道,TCP会有一个三次握手那么实际上也就是会有1次RTT:
如果是HTTPS的话还会使用SSL/TLS的额外握手,就会有3次RTT:
那么0RTT的建立链接QUIC是怎么做到的呢?这里得先说一下QUIC的0RTT并不是完全的0RTT,他同样需要1RTT去做一次秘钥协商,在QUIC中使用的是Diffie-Hellman密钥交换,该算法是一种建立密钥的方法,并非加密方法,但其产生的密钥可用于加密、密钥管理或任何其它的加密方式,这种密钥交换技术的目的在于使两个用户间能安全地交换密钥(KEY)以便用于今后的报文加密。DH算法用了离散对数的相关知识,这里就不扩展讲解,有兴趣的可以下来搜索这种算法。QUIC通过DH算法创建一个安全的连接后,客户端会缓存起来原始的连接信息等。在后续的过程中只要和同一个服务器建立链接都是直接发送数据,不需要再次协商秘钥,从而实现了后续的0RTT。
更为出色拥塞控制
TCP的拥塞控制的算法特别多,比如基于丢包反馈的(Tahoe、Reno、New Reno、SACK), 基于延时反馈的(Vegas、Westwood),其中的Reno也就是我们最为熟悉的,它分为四个阶段:慢启动,拥塞避免,快速重传,快速恢复。
而在QUIC中使用了更为优秀的机制来控制拥塞控制,它可以针对不同业务,不同网络制式,甚至不同的RTT,使用不同的拥塞控制算法。同时也会采用了packet pacing来探测网络带宽,来提升网络使用率。
更好的重传机制
在重传的机制中有一个比较重要的名词,那就是RTO(Retransmission Timeout) 重传超时时间,一般这个数据会根据RTT去进行计算,那么我们有一个更精确的RTT肯定就可以有一个更好的RTO。
在TCP中重传的时候序列号不变,会导致我们的RTT算得不准确,比如重传的时候你不知道你这次请求到底是和原始请求匹配还是和重试请求匹配,就会导致我们的采样RTT不准确。
在QUIC中序列号都是递增的,并且通过offset来确定在包中的真实位置,这样就可以得到更为准确的RTT。
在TCP中计算RTT的方法就是发出的时间和响应回来的时间相减,但是这样算出的时间不准确,在QUIC中会减去服务端Ack Delay的时间,这样的话就更为精准。
同样的在TCP中有个SACK选项,该选项打开时用于记录传输过程中一些没有被确认的数据的范围,便于后续定向重传多组丢失数据,而不是全部重传,所以更多的范围便于更多的选择重传,也意味着更少的重传包频率。但TCP最多支持3个SACK范围,而QUIC能支持255个。
没有队头阻塞的多路复用
熟悉HTTP2.0的同学应该知道在2.0中如果访问同一个服务器只会有一个TCP连接,所有的请求都会走这条连接:
而每个请求在Connection中叫做Stream,一个Connection中可以有多个Stream,这里有个问题是在TCP中的包是保证时序的,如果某个Stream丢了一个包,他同时也会影响其他的Stream,在更为严重的时候反而多路复用还不如HTTP1.1的多个链接。
而在QUIC中,因为底层是基于UDP,UDP不需要保证包的时序,只会在接收包的时候对包进行重组,所以不会存在这个问题。这也就是为什么Google提议在HTTP3中使用QUIC的原因。
更优秀的流量控制
上面说了QUIC是多路复用的,在QUIC中可以针对Stream和Connection都进行流量控制。
QUIC 的流量控制和 TCP 有点区别,TCP 为了保证可靠性,窗口左边沿向右滑动时的长度取决于已经确认的字节数。如果中间出现丢包,就算接收到了更大序号的 Segment,窗口也无法超过这个序列号。 但 QUIC 不同,就算此前有些 packet 没有接收到,它的滑动只取决于接收到的最大偏移字节数。
最重要的是我们可以进行动态配置,可以在内存不足或者上游处理性能出现问题时,通过流量控制来限制传输速率,保障服务可用性。
连接迁移
现在在手机上移动流量和wifi的切换是一个比较常见的事,每次切换ip地址都会发生变化,如果是TCP的话连接就会中断从而进行重新建立链接。
在QUIC不再以 IP 及端口四元组标识,而是以一个 64 位的随机数作为 ID 来标识,通过这样的方式可以进行连接重复利用,不会重新建立新的连接。
其他
在QUIC中还有更多的其他的特性,比如:
- 通过header stream保证流顺序
- 底层保证连接持久
- 源地址令牌防止地址欺骗
- 握手时压缩证书避免放大攻击这里就不一一介绍了
这里就不详解介绍了,大家可以自行查阅资料搜索。
总结
其实这篇帖子也算是一个扫盲贴,相信有很多朋友没有听说过RUDP相关的一些东西,或者说听说过但是一直以为他是一个很复杂,很难理解的东西,其实在这里摊开来讲RUDP就是一个UDP+应用层可靠协议组成的,希望大家看完这篇文章后,能有所收获。
参考文章:
- QUIC协议是如何做到0RTT加密传输的: https://blog.csdn.net/dog250/article/details/80935534
- 技术扫盲-新一代基于UDP的低延时网络传输层协议——QUIC详解 :http://www.52im.net/thread-1309-1-1.html
- QUIC协议的分析,性能测试以及在QQ会员实践:https://www.cnblogs.com/wetest/p/9022214.html
如果大家觉得这篇文章对你有帮助,你的关注和转发是对我最大的支持,O(∩_∩)O: