QUIC 启动!

news2024/10/23 7:54:11

掘金地址:https://juejin.cn/post/7428200842229006377

引言

QUIC是什么?明明你每天都在用,明明每天都在timing,难道你不知道吗?啊?不会吧,不会吧。

img

那就让本文来让你全方位的了解这个协议。

一、QUIC是什么

QUIC协议的提出有其背景原因。随着网络技术的不断进步和发展,人们的在线娱乐需求也在逐渐升级。从前,人们或许满足于观看预先录制好的视频片段。但现在,用户们不再满足于此,他们渴望体验到更加即时且互动性更强的直播形式。

006APoFYly1fwpb28mamug308w08wqgy

然而,传统的TCP协议因存在头部阻塞问题和慢启动问题,难以实现这种低延迟传输的要求。在这种背景下,谷歌公司作为这种好心人,为了满足这种需求,推出了QUIC(Quick UDP Internet Connections,快速UDP互联网连接)这一全新协议。

尽管QUIC看似是一种在应用层实现的协议,但实际上它提供的是传输层的功能。那么,QUIC究竟属于哪一层呢?

我们从维基百科可以看到是一种传输层协议:

image-20241020131002824

那有读者疑问就来了,干嘛整这么复杂呢???传输层就传输层,应用层就应用层,干嘛来一个不伦不类的基于应用层实现的传输层协议?

其实也是有苦衷的:

  1. 传输层协议实现过于复杂

  2. 协议的话,写入的都是在操作系统内核中,如果新增了一个协议,需要对全世界所有系统都进行重装,那可真是更麻烦了

看到这里,我只能说:

006APoFYly1g22j8nniyfj30h50hs42m

二、QUIC 核心功能

在开始之前,我们先来一幅图,让我们对比Http1.1、Http/2、QUIC三者之间的区别:

image-20241020132925390

从图中,我们可以看出,没看出也没事,但是我们知道的是QUIC的设计也是参照了Http/2实现的。实现的功能我们先列举出来:

  • 快速握手和连接迁移

  • 自适应流控和多路复用Stream

  • 错误重传

  • 拥塞控制

  • 安全性

接下来,我们一一来说:

img

2.0、头部设计

要基于 UDP 实现的可靠传输协议,那只能要设计好协议的头部字段。拿 HTTP/3 举例子,在 UDP 报文头部与 HTTP 消息之间,共有 3 层头部:

  • QUIC packet(包)头部:建立连接

  • QUIC frame(帧)头部:进行传输

  • Http/3 帧头部:与HTTP头部有关联,不关传输的事

image-20241020140634208

这里有个印象即可,等下会针对重要头部信息进行细说。

2.1、连接建立

2.1.1、快速握手

对于HTTP/1和HTTP/2协议,HTTPS的加密是分层实现的:

  1. TCP三次握手(1RTT)

  2. TLS四次握手(2RTT)

这意味着,通常需要3个RTT(往返时间)才能开始传输数据。即使使用Session会话复用,也需要至少2个RTT。

而对于HTTP/3(使用QUIC),情况有所不同:

  • 首次连接:QUIC内部集成了TLS,使用TLS 1.3协议,仅需1个RTT即可完成连接建立与密钥协商。

  • 复用连接:第二次连接复用时,应用数据与QUIC握手信息一起发送,实现0-RTT的效果。

image-20241021110054347

细谈谈连接过程:(这部分了解即可,其实就是建立连接与TLS连接融合在一起了)

  1. 客户端发起连接:客户端发送一个初始的QUIC数据包

  • 初始数据包头部:该头部包含一个随机生成的连接ID,用于标识这条QUIC连接。

  • TLS ClientHello 消息:QUIC结合了TLS 1.3的握手机制,客户端首先发送TLS ClientHello消息,包含其加密参数和其他握手所需信息。

由于QUIC使用的是UDP协议,所以不需要像TCP那样的三次握手过程,客户端在发送第一个数据包时就可以携带应用层数据,降低了连接的延迟。

  1. 服务器响应:服务器接收到客户端的初始包后,进行如下操作:

    • 验证客户端的初始包:服务器检查客户端的连接ID和相关信息。

    • 返回TLS ServerHello 消息:服务器返回自己的加密参数,并确认TLS握手的信息。如果需要,服务器可能还会返回一个Token来进行客户端验证(防止DoS攻击)。

    • 携带加密确认的消息:服务器返回的ServerHello消息中携带了加密确认和部分握手信息,这意味着部分加密已经完成。

此时,QUIC连接尚未完全建立,仍处于握手阶段,但加密通道已经部分建立,后续的数据包可以通过加密的方式传输。

  1. 客户端确认:客户端收到服务器的ServerHello消息后,完成剩余的TLS 1.3握手流程:

    • 客户端完成握手:客户端基于服务器的加密参数,生成并发送一条消息来确认加密通道的建立。

    • 交换应用数据:完成握手后,客户端和服务器可以开始传输应用层数据。

在这个阶段,QUIC连接就完全建立,双方可以在加密的情况下传输数据。

https://zhuanlan.zhihu.com/p/301505712

2.1.2、连接迁移

讨论完初始连接后,让我们转向QUIC连接复用的话题:

在复用已有连接时,QUIC能够实现0-RTT(零往返时间),这是因为复用基于之前握手过程中协商得出的连接ID来实现。这一机制不仅简化了后续交互的过程,还极大地提高了效率。

image-20241022120319782

想象一下你在玩一个在线游戏,从家里的Wi-Fi网络切换到外面的4G网络。如果使用传统的TCP协议,这种切换可能会导致游戏卡顿或断线。但在QUIC协议下,情况完全不同:

当你在家用Wi-Fi玩游戏时,QUIC会为你的连接分配一个唯一的连接ID。当你离开家,手机自动切换到4G网络时,QUIC会使用同一个连接ID来标识连接。这样一来,即使网络变了,游戏仍然可以无缝继续,不会有任何中断或延迟。

这种设计确保了QUIC协议下的通信能够在不同的网络环境下平滑过渡,提供更好的用户体验。

2.1.3、连接原理解析 —— QUIC packet(包)头部

要理解QUIC协议如何建立连接,首先需要解析用于建立连接的QUIC包头(Packet Header)结构:

image-20241022120639114

QUIC包头可以细分为两种类型:

  1. 长包头(Long Packet Header):用于初始连接的建立;

  2. 短包头(Short Packet Header):用于常规的数据传输。

QUIC使用三次握手来建立连接,其主要目标是为了协商连接ID。一旦协商出了连接ID,后续的传输过程中,双方只需要维持该连接ID不变,这样就可以支持连接迁移的功能。因此,在常规数据传输中使用的短包头中,不再需要包含源连接ID字段,而只需要包含目的连接ID。

短包头中的包编号(Packet Number)是每个报文唯一的标识符,并且它是严格递增的。这意味着即使某个特定的包(如Packet N)丢失并需要重传,重传的包的编号也不会再是N,而是一个大于N的数值。

2.2、数据传输

2.2.0、QUIC Frame Header

QUIC的数据传输是在QUIC Frame Header中进行的;一个Packet报文中可以存放多个QUIC Frame。先来看看它的整体结构:

image-20241022133030180

  • Stream ID:用于区分多个并发传输的HTTP消息,类似于HTTP/2中的Stream ID。

  • Offset:类似于TCP协议中的Seq序号,保证数据的顺序性和可靠性。

  • Length:指明Frame数据的长度。

通过引入Frame Header,Stream ID + Offset 字段信息实现数据的有序性。通过比较两个数据包的Stream ID与Offset,如果都一致,说明这两个数据包的内容一致。

2.2.1 、自适应流控

首先,我们来回顾一下TCP的流量控制是如何实现的。

TCP的流量控制机制是基于接收方告知发送方其当前接收窗口大小的原理,从而使发送方能够根据接收方的实际接收能力调整其发送速率。这就好比在学校食堂打饭时,为了不浪费食物,学生会根据自己的食量告诉打饭的阿姨要多少份量的食物。同样,在TCP中,接收方会定期向发送方报告其缓冲区还有多少空间可供使用,发送方则据此调整其发送的数据量。

而在QUIC协议中,流量控制机制更加精细且层次分明:

  • Stream级别的流量控制:在QUIC协议中,每个Stream(可以理解为一条HTTP请求)都有其独立的滑动窗口机制来进行流量控制。这样可以确保任何一个Stream不会独占整个连接的接收缓冲区,从而避免因单个Stream的数据量过大而导致的缓冲区溢出。

  • Connection级别的流量控制:QUIC不仅提供了Stream级别的流量控制,还实现了Connection级别的流量控制,即对连接中的所有Stream所发送的数据总量进行限制,防止发送方的数据总量超出接收方的缓冲区容量。

总的来说,QUIC的流量控制机制不仅细化到了单个流级别,还从整体连接的角度进行了把控,从而提供了比TCP更灵活且高效的传输性能。

流控这块,如果希望详细了解的话,可以看这篇文章:https://juejin.cn/post/7066993430102016037#heading-5

2.2.2、 多路复用Stream

QUIC实现的多路复用Stream我只能说跟Http/2太像了,都是基于Stream实现的并发传输,但是呢?Http/2有一个大 Problem——队头阻塞(即一个Stream中包丢失,则阻塞全部请求),因为它始终复用的只是一个TCP面向连接的传输信道,但是QUIC可不一样,是基于UDP实现的无连接传输,所以在多路复用Stream的时候才算是真真正正的实现无干扰的多路复用Stream,显著提升了网络传输的效率和响应速度

image-20241021220430173

2.3 、错误重传

2.3.1、定时器和ACK/NACK机制

QUIC通过定时器和ACK/NACK机制来检测丢包并进行重传。接收方定期发送ACK报文告知已接收的数据包。若数据包丢失,接收方不发送ACK,发送方通过定时器检测并在超时后重传。此机制类似TCP,但更灵活高效。

2.3.2、前向纠错(FEC)

QUIC利用FEC技术减少重传次数。发送端编码原始数据并添加冗余信息,接收端用这些信息恢复丢失的数据包。例如,海明码通过冗余位进行错误校验和纠正。

2.4、拥塞控制

QUIC的拥塞控制机制非常类似于TCP,但更加灵活和智能。它使用了类似TCP的拥塞控制算法,比如CUBIC(慢开始、拥塞避免、快重传、快恢复策略),来调节发送速率并避免网络拥塞。拥塞控制的核心思想是根据网络拥塞的程度调整发送数据的速度,以最大限度利用带宽,同时避免过度负载。

与TCP不同的是,QUIC可以利用自己的流控和拥塞控制机制在多个独立的数据流上并发应用这些控制策略,使得网络资源的利用更加高效,特别是在高延迟或高丢包率的网络环境中。

2.5、总结优势

综上所述,QUIC对比与Http/2最大的亮点主要体现在以下三个方面:

  1. 无队头阻塞:QUIC通过独立的数据流设计,避免了由于单个数据包丢失而导致整个连接阻塞的问题,从而提高了传输效率。

  2. 更快的连接建立:QUIC优化了连接建立过程,减少了握手延迟,使得客户端与服务器之间的连接建立速度更快。

  3. 连接迁移:QUIC支持无缝的连接迁移,允许客户端在不中断现有连接的情况下改变其IP地址或端口,这对于移动设备在网络切换时保持持续连接尤其重要。

这三点优化使得QUIC在具备与TCP类似的流控和拥塞控制功能的同时,具有更大的优势。

再谈谈一些实际的测试用例吧,这里以网易的弱网环境测试为例:https://juejin.cn/post/7091478561613152269?searchId=202410201416118B99FD352B15EF1724DB#heading-4

6.png

发现明显的会比TCP相应快个几百ms,这对系统性能还是优化挺大的。

三、面临的挑战

  1. 路由器和防火墙限制:一些网络设备可能限制或封堵UDP流量,尤其是443端口上的UDP流量,这是QUIC常用的端口。这可能导致QUIC流量被意外拦截或丢弃。

  2. QoS(Quality of Service)问题:由于QUIC使用UDP,某些网络服务提供商可能会误认为大量的UDP流量是潜在的DDoS攻击,并采取措施限制或丢弃这些流量。

  3. 部署难度: 目前 QUIC 的部署相对较为复杂,需要网络和服务器端的双方都支持。

  4. 协议升级: QUIC 协议仍在不断发展,升级过程中可能会涉及到版本兼容性的问题。

  5. caniuse?

image-20241022111723351

四、应用与启动

4.1、应用场景

应用场景:

  1. HTTP3:弱网环境也可流畅访问

  2. 低延迟直播:延迟从2s到200ms

  3. 更多领域:真正即时通讯、网络游戏、物联网

4.2、如何在浏览器中启动

  1. 火狐浏览器

    1. 访问:about:config

    2. 启用:network.http.http3.enabled

  2. Chrome 浏览器

    1. 访问:chrome://flags

    2. 启用:enable-quic

  3. 测试是否已经支持 QUIC:

    1. 测试网站: https://quic.nginx.org/

    2. HTTP Indicator插件

  • img

也可以这么来测试:根据F12,查看网络,然后打开协议,我们可以看到其实现在浏览器主流使用的还是Http/2,少部分网站中使用的CDN采用的是Http/3

image-20241022151003298

五、总结

QUIC(Quick UDP Internet Connections)是由谷歌推出的新型传输层协议,旨在提供低延迟的可靠传输服务。通过实现下面三个核心功能:

  • 快速握手:仅需1个RTT即可完成连接建立。

  • 连接迁移:支持无缝的连接迁移。

  • 多路复用:无队头阻塞,多个Stream并发传输。

取得了代替TCP连接,成为Http/3底层使用的传输协议。

参考文章:

  • https://zhuanlan.zhihu.com/p/32553477

  • 4.17 如何基于 UDP 协议实现可靠传输? | 小林coding

  • https://juejin.cn/post/7066993430102016037#heading-21

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2221432.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

word表格跨页后自动生成的顶部横线【去除方法】

Hello World! Its been a long time. 这一年重心放在了科研、做事、追寻新的经历上,事有正事、琐事、幸事、哀事,内心与认知成长了一些,思想成熟了几分,技艺也有若干收获。不管怎样,来打个卡吧,纪念一下&…

爬虫日常实战

爬取美团新闻信息,此处采用两种方法实现: 注意点:因为此处的数据都是动态数据,所以一定要考虑好向下滑动数据包会更新的情况,不然就只能读取当前页即第一页数据,方法一通过更新ajax数据包网址页数&#xf…

【MyBatis】初识MyBatis 构建简单框架

目录 MyBatis前言搭建一个简单的MyBatis创建Maven项目引入必要依赖创建数据表结构创建User实体类创建Mapper接口Mapper层Dao层 创建MyBatis的Mapper映射文件编写测试类传统测试类JUnit测试 MyBatis 介绍:MyBatis是一款半自动的ORM持久层框架,具有较高的…

利用自定义 ref 实现函数防抖

今天来简单介绍一个新的方法,使用自定义 ref 实现函数防抖。 1. 自定义 ref 的来源 自定义 ref 防抖函数来自于前端开发中的两个概念:Vue 的响应式系统 和 数防抖(Debounce)。 1、Vue 响应式系统:Vue 提供了 ref 和…

Python学习的自我理解和想法(20)

#1024程序员节|征文# 学的是b站的课程(千锋教育),跟老师写程序,不是自创的代码! 今天是学Python的第20天,学的内容是面向对象中的私有属性,私有方法,多态,单例计模式。开…

【ubuntu18.04】ubuntu18.04升级cmake-3.29.8及还原系统自带cmake操作说明

参考链接 cmake升级、更新(ubuntu18.04)-CSDN博客 升级cmake操作说明 下载链接 Download CMake 下载版本 下载软件包 cmake-3.30.3-linux-x86_64.tar.gz 拷贝软件包到虚拟机 cp /var/run/vmblock-fuse/blockdir/jrY8KS/cmake-3.29.8-linux-x86_64…

spring源码中的,函数式接口,注解@FunctionalInterface

调用方 /org/springframework/beans/factory/support/AbstractBeanFactory.java:333sharedInstance getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It mi…

高级的SQL查询技巧有哪些?

成长路上不孤单😊😊😊😊😊😊 【14后😊///C爱好者😊///持续分享所学😊///如有需要欢迎收藏转发///😊】 今日分享关于高级SQL查询技巧方面的相关内容&#xf…

MATLAB人脸考勤系统

MATLAB人脸考勤系统课题介绍 该课题为基于MATLAB平台的人脸识别系统。传统的人脸识别都是直接人头的比对,现实意义不大,没有一定的新意。该课题识别原理为:先采集待识别人员的人脸,进行训练,得到人脸特征值。测试的时…

HomeAssistant自定义组件学习-【一】

#环境准备# 按官方的步骤准备就可以,我是在Windows下使用VS Code开发的,安装了WSL(使用模板创建组件需要在WSL环境下完成) 官方链接:https://developers.home-assistant.io/docs/development_environment 环境准备好…

力扣困难题汇总(14道)

题4(困难): 思路: 找两数组中位数,这个看起来简单,顺手反应就是数第(mn)/2个,这个难在要求时间复杂度为log(mn),所以不能这样搞,我的思路是:每次切割长度为较…

【K8s】Kubernetes 词汇表

微思网络 厦门微思网络 K8S认证工程师(CKA)备考与学习指南https://mp.weixin.qq.com/s/XsEVpU7dKnJDBopynWW3GQ K8S-CKA课程试听:Container 概述 词汇表 此术语表旨在提供 Kubernetes 术语的完整、标准列表。其中包含特定于 Kubernetes 的技术术语以及…

uniapp修改input中placeholder样式

Uniapp官方提供了两种修改的属性方法&#xff0c;但经过测试&#xff0c;只有 placeholder-class 属性能够生效 <input placeholder"请输入手机验证码" placeholder-class"input-placeholder"/><!-- css --> <style lang"scss" s…

redis的zset实现下滑滚动分页查询思路

常规zset查询 我们redis的数据为 我们知道 我们常规查询的话 我们假如 zset 表中 有7个元素&#xff0c;然后我们进行分页查询的话&#xff0c;我们一次查3个元素&#xff0c;然后查出来元素 和元素的分数 我们redis的语法应该这样写 zrevrangebyscore wang 1000 0 withsc…

kotlin实现viewpager

说明:kotlin tablayout viewpager adapter实现滑动界面 效果图 step1: package com.example.flushfragmentdemoimport androidx.appcompat.app.AppCompatActivity import android.os.Bundle import androidx.fragment.app.Fragment import androidx.viewpager2.adapter.…

【uni-app学习-2】

一、跳转 方法&#xff1a;在methods中去定义方法&#xff1a; 上述为直接跳转&#xff0c;但是当你要跳转页面是由多个可切换页面组成比如&#xff1a; 这个页面其实是由两个页面组成&#xff0c;一个主页&#xff0c;一个我的&#xff0c;两个页面 路由配置需要用到toob…

java--多态(详解)

目录 一、概念二、多态实现的条件三、向上转型和向下转型3.1 向上转型3.2 向下转型 四、重写和重载五、理解多态5.1练习&#xff1a;5.2避免在构造方法中调用重写的方法&#xff1a; 欢迎来到权权的博客~欢迎大家对我的博客提出指导这是我的博客主页&#xff1a;点击 一、概念…

EasyExcel自定义下拉注解的三种实现方式

文章目录 一、简介二、关键组件1、ExcelSelected注解2、ExcelDynamicSelect接口&#xff08;仅用于方式二&#xff09;3、ExcelSelectedResolve类4、SelectedSheetWriteHandler类 三、实际应用总结 一、简介 在使用EasyExcel设置下拉数据时&#xff0c;每次都要创建一个SheetWr…

韩语干货topik韩语考级柯桥外语培训韩语中的惯用表达

表示递进的词尾或惯用表达 1 -을/ㄹ 뿐만 아니라 接在动词和形容词词干后面&#xff0c;表示“不仅...而且...”。该语法需要注意前后会有两个动词或形容词&#xff0c;此时两个动词或形容词的时态应保持一致。 例: 한번 파괴된 자연은 되돌리기기 쉽지 않을 뿐만 아니라 지역…

Java项目实战II基于微信小程序的原创音乐平台{UNIAPP+SSM+MySQL+Vue}(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在数字音乐…