首页 > 其他分享 >CDN传输加速—QUIC在短视频加速上的技术落地

CDN传输加速—QUIC在短视频加速上的技术落地

时间:2022-11-08 00:33:28浏览次数:55  
标签:QUIC CDN DCC TCP server RTT quic 加速

导语:QUIC (Quick UDP Internet Connection,快速UDP互联网连接) 是一个新的基于UDP的多路复用且安全的传输协议。它从头开始设计,完全弃用了TCP,使用UDP作为底层传输协议。QUIC提供了等价于HTTP/2 的多路复用和流控,等价于 TLS 的安全机制,及等价于 TCP的连接语义、可靠性和拥塞控制。据国际互联网工程任务组(The Internet Engineering Task Force,简称 IETF )消息,HTTP-over-QUIC 实验性协议将被重命名为 HTTP/3,并有望成为 HTTP 协议的第三个正式版本。

本文将介绍QUIC协议在CDN技术上,腾讯多媒体的应用落地,以及相比于TCP所带来的极快的优化体验,并尝试分析QUIC到底快在哪里?


1、背景

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

 

2、封装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。

descript 图1、QUIC Client SDK

 

3、QUIC Client在MCP++框架上的应用

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

  • 1)、QUIC由于其复杂的特性实现,运行在应用层的协议栈,需要大量的CPU计算。
  • 2)、以及QUIC Client自成一体的UDP Socket收发,DCC原本的epoll_wait单线程模型无法支持,很难改造。

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

descript 图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发送和接收两种场景,分为发送失败和接收失败。

descript 图3、QUIC请求与回退流程

DCC->QUIC请求流程:

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

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

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

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

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

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

  • a. 发送成功,SUCCESS流程结束,异步等待queue响应。
  • b. 发送失败,flow连接回退到TCP,当前请求消息通过TCP重试。
  • c. Stream busy,QUIC所有Stream都处在忙状态,连接不回退,只有当前请求使用tcp发送。
descript 图4、DCC接收QUIC响应流程

QUIC->DCC响应流程:

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

2、DCC线程send_mq_request_by_quic从队列Dequeue 取出响应消息。

  • a). QUIC_SUCCESS,将响应消息enqueue 发给mcd。
  • b). 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大大减少了三次握手的等待时间。而我们在CDN上的应用更进一步,front->zone的分布式集群所有机器之间的请求,除了第一次,以后均可以实现0-RTT建链。

descript 图5、QUIC 0-RTT

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

在当前的CDN架构上要实现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优化效果明显。尤其是在弱网下,传输时延大大降低:

descript

a)、国内以长沙电信为例,回源延时219ms -> 88ms,优化效果能达到59.8%,回传原本延时就比较低了,延时优化效果也能达到25%。

descript

b)、海外以美国点为例,RTT比较高的场景196ms,QUIC的回源回传效果更加明显1.3s->339ms,优化率达到73.9%。

descript

 

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级别的流控窗口,真正从传输层解决队头阻塞的问题。

从客户端和CDN服务器的统计上看到,同一连接多个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才判断丢包进行快重传。

详细描述:QUIC协议研究(五):QUIC Loss Detection丢包探测 http://km.oa.com/group/15624/articles/show/397474

 

7、总结

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

 

转载请注明出处,商用请征得作者本人同意。 

 

文章首发于公众号:【昭景成】,id:zhaojc100。

欢迎关注,BAT攻城狮,和你一起聊聊职场、聊聊技术、聊聊互联网上的那些事儿。

 

标签:QUIC,CDN,DCC,TCP,server,RTT,quic,加速
From: https://www.cnblogs.com/zhaojc100/p/16867980.html

相关文章