IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> QUIC在CDN节点间的技术落地 -> 正文阅读

[网络协议]QUIC在CDN节点间的技术落地

背景

在现有物理资源的情况下,CDN海外机房回源、回传延迟较高,RTT最高有几百毫秒,TCP丢包率和成功率表现也不尽人意,一个大视频分片的上传下载需要几秒时间。而QUIC的特性在网络传输,尤其是弱网情况下,效果相比TCP好很多。多段256 NACK、更加激进的Loss Detection丢包探测和重传机制、以及0-RTT的握手建立,使其相比TCP的传输延迟大大降低。

1.封装QUIC Client SDK

QUIC运行在用户空间,底层使用UDP作为传输协议。客户端侧主要涉及QuicConnection、QuicStream、QuicSession三个核心功能类。

QuicConnection:负责管理QUIC连接,创建Connectionid,完成QUIC的握手(1-RTT/0-RTT),确保连接建立。

QuicSession:会话管理,管理QUIC整个会话的生命周期。包括QuicConnection、各种定时器Alarm、以及多Stream的生命周期等。

QuicStream:QUIC真正进行数据传输的媒介,支持多个QuicStream并发传输,Stream之间的数据丢包重传等互不影响,真正消除TCP协议的队头阻塞缺陷。

QUIC协议在应用层实现了原本TCP几乎所有的特性:传输窗口、ACK、多路复用、Loss Detecion、流量控制、拥塞控制等等,非常复杂。

所以在工程实现上我抽取了chromium的net库等

重载QuicStream、QuicSession等,封装成易于理解的QUIC Client SDK,提供quic_socket、quic_connect、quic_send、quic_recv等开发者比较习惯的socket使用方式API。

在这里插入图片描述
图1. QUIC Client SDK

2. QUIC Client 在MCP++框架上的应用

MCP++框架主要是DCC模块负责对外的请求下载等,在CDN上的应用的话,Front节点的回源、回传都需要通过DCC去下载和上传。

◎ QUIC由于其复杂的特性实现,运行在应用层的协议栈,需要大量的CPU计算。

◎ 以及QUIC Client自成一体的UDP Socket收发,DCC原本的epoll_wait单线程模型无法支持,很难改造。

故而决定采用【DCC线程 + QUIC线程】的模型支持QUIC协议,QUIC Client线程保持高度的自治,请求与响应皆自我完善。DCC原本的连接管理,CRawCache等需要自己实现。

在这里插入图片描述
图2. MCP DCC与QUIC交互

如图2所示,DCC与QUIC交互主要有两个流程,不破坏现有DCC框架:

1、send_mq_request_by_quic负责将来自mq的请求发给QUIC,由quic创建UDP socket发送出去。

2、handle_network_recive_quic负责从队列queue里取出QUIC接收完处理后的响应消息。

3. QUIC请求流程&失败回退到TCP机制

由于QUIC底层通过UDP进行连接,该战略级应用的几万台机器所处不同的运营商和网路环境,无法保证各种中间设备UDP和端口都可用。所以在设计时不能完全依赖UDP可信,要考虑失败回退TCP机制。

DCC与QUIC的交互有:

  • send_mq_request_by_quic;
  • handle_network_recive_quic;
  • 发送和接收两种场景,分为发送失败和接收失败。

在这里插入图片描述
图3 QUIC请求与回退流程
DCC->QUIC请求流程:

  • epoll_wait接收来自MCD的管道mq事件。

  • 判断请求QUIC or TCP,用QUIC 则send_mq_request_by_quic。

  • 判断当前要请求的flow连接是否已回退到TCP,已回退的话这里直接走TCP。

  • QUIC,GetQuicConn(flow)获取QUIC连接id,连接存在直接请求,不存在quic_connect()发起握手创建连接。

  • connect失败(直接返回失败,有些场景不会直接返回失败),flow连接回退到TCP(后续该连接其他消息30分钟内走TCP),当前请求消息通过TCP重试。

  • connect成功,quic_send()发送数据:

  • 发送成功,SUCCESS流程结束,异步等待queue响应;

  • 发送失败,flow连接回退到TCP,当前请求消息通过TCP重试;

  • Stream busy,QUIC所有Stream都处在忙状态,连接不回退,只有当前请求使用tcp发送。
    在这里插入图片描述
    图4 DCC接收QUIC响应流程
    QUIC->DCC响应流程:

1.QUIC接收校验完毕check_complete后,将响应消息入队列queue。

2.DCC线程:send_mq_request_by_quic

从队列Dequeue 取出响应消息。

  • QUIC_SUCCESS,将响应消息enqueue 发给mcd;
  • CONN_ERROR,连接中断,将QUIC传来的消息进行TCP重发,flow连接回退到TCP。

0-RTT场景下,quic_connect()发出去CLHO后client端即认为连接成功,调用quic_send()发送数据(数据缓存在QUIC底层buff),实际握手可能会超时失败。OnConnectionClose 失败后需要通过queue通知DCC线程做相应的处理。

4. 0-RTT

QUIC比TCP快的一个很大特点是其握手使用了更少的RTT,甚至达到0-RTT握手,直接进行数据传输,相比TCP大大减少了三次握手的等待时间。而我们在该战略级应用更进一步,front->zone的分布式集群所有机器之间的请求,除了第一次,以后均可以实现0-RTT建链。
在这里插入图片描述
图5. QUIC 0-RTT

背景:

QUIC handshake握手阶段服务端REJ时会下发server_config和token给客户端。客户端下次握手时,如果携带上次下发的server_config和token到服务端,服务端验证通过,即可实现0-RTT。

问题:

在该应用当前架构上要实现0-RTT,有几个问题需要解决:

  1. 服务端front有多个ccd进程,每个进程生成的server_config都不一样,客户端携带上次的server_config请求到其他ccd进程时,服务端校验不通过,无法0-RTT?

  2. 客户端ip不是固定的,4G/WIFI切换时每次都会变换ip,服务端下发的token融合了客户端的ip,客户端的ip变化时,携带的token服务端校验不通过,无法0-RTT?

  3. 服务端ip对于客户端来说不是固定的,服务端是一个集群,请求新的服务器ip时,如果当前client没有请求过该server_id,本地没有缓存过新server的cache(server_config等),就无法实现0-RTT。

解决方案:

问题1:服务端所有front集群固定生成同一个server_config_id。

问题2:服务端关闭token验证开关,QUIC提供关闭验证的开关,在应用层即可关闭。

问题3:客户端每次构建新的请求连接时使用相同的server_id(host,port)。Server_id是缓存在客户端本地,用来指引cache的key, 对于客户端来说,这相当于把对端所有server集群看成同一个server,对同一个server进行下次握手,就会直接发起full CLHO消息。服务端那边校验server_config通过,就能建立新的连接了。

5. QUIC对比TCP的优化效果

线上灰度观察效果,QUIC优化效果明显。尤其是在弱网下,传输时延大大降低:
a)、国内以长沙电信为例,回源延时大幅度降低,优化效果能达到59.8%,回传原本延时就比较低了,延时优化效果也能达到25%。
在这里插入图片描述

b)、海外以美国节点为例,QUIC的回源回传效果更加明显,优化率分别达到73.9%和75.7%。
在这里插入图片描述

6. QUIC快在哪里?

QUIC的提升效果表现如此的好,究竟比TCP快在什么地方呢?TCP协议经过几十年的发展,可以说构建了整个互联网的基础。Google为了开发QUIC做了很多工作,基本上把整个TCP的协议栈都重新实现了一遍(取其精华,修复缺陷)。尝试分析一下:

1. 0-RTT

TCP的三次握手带来必定的1-RTT消耗,在网络状况比较好的情况下,大部分的消耗可能都来自业务,不觉得RTT耗时很多。但是在网路状况差的情况下(比如上面的美国),1个RTT就带来196ms的延时,使用QUIC优化后,可以看出整体耗时只有339ms,所以0-RTT对于秒开业务来说是一个很重要的特性。

2. QUIC Stream多路复用 — TCP 队头阻塞

QUIC支持多路复用,QUIC的底层UDP不进行排序和确认,只负责传输,ACK、确认、排序等都在QUIC进行。TCP当有多个流同时传输时,如果某个流发生了丢包,其他流需要等待其重传排序完成才能继续传输,因为TCP的滑动窗口只有一个,队头阻塞无法避免。而QUIC的多个Stream之间重传、排序等互不干扰,有stream级别的流控窗口,真正从传输层解决队头阻塞的问题。

从应用的统计上看到,同一连接多个Stream同时传输的场景非常频繁。而去除了队头阻塞的QUIC延时比TCP低就很明显了,并且在弱网丢包率高场景下,表现更好。

3. Up to 256 NACK ranges,支持256分段ACK

TCP每次只会ACK一个数据包,当滑动窗口用尽之后,只能等待新的ACK到来才能继续发送新数据包。就算开启了SACK,最多也只能ACK三个包。

QUIC最大支持ACK 256个数据包,支持分段ACK。就算某个ACK包丢失,后续其他包的ACK也能带上之前ACK过的包号。

4. Loss Detection丢包探测

QUIC在TCP的经验之上重新构建了一种新的丢包探测机制:FR快重传、ER早期重传、RTO、TLP、F-RTO,和TCP相比很大不同。表现为更为激进的丢包发现和重传策略:比如如果收到最大的ACK包号大于3就判断丢包进行FR重传;而TCP需要收到连续三个重复的ACK才判断丢包进行快重传。

7.总结

本文介绍当前主流的基于chromium的QUIC Client SDK的架构,以及其在腾讯某战略级应用的MCP++框架上的工程落地。详细介绍了MCP++框架上的 DCC+QUIC 多线程lib方案,和QUIC回退到TCP的保障机制,另外简单介绍了下全面 0-RTT 在 Front->zone 上实现存在的问题和解决方案。通过在线上落地使用QUIC,与TCP相比,加速效果显著。QUIC拥有0-RTT、多路复用、256NACK等优秀特性,是一个潜力很大的技术。IETF已经将HTTP over QUIC重命名为HTTP3,随着下一代HTTP3协议的普及,QUIC将应用的更加广泛。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-08-21 15:48:48  更:2021-08-21 15:49:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:19:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码