找回密码
 会员注册
查看: 24|回复: 0

QUIC在CDN节点间的技术落地

[复制链接]

5

主题

0

回帖

16

积分

新手上路

积分
16
发表于 2024-9-20 18:11:28 | 显示全部楼层 |阅读模式
本文共计:3430字;阅读需要:8分钟;作者:艾硕,腾讯TEG基础架构部资深工程师目录导语1.封装QUICClientSDK2.QUICClient在MCP++框架上的应用3.QUIC请求流程&失败退回到TCP的机制4.0-RTT5.QUIC对比TCP的优化效果6.QUIC快在哪里?7.总结START导语QUIC(QuickUDPInternetConnection,快速UDP互联网连接)是一个新的基于UDP的多路复用且安全的传输协议。它从头开始设计,完全弃用了TCP,使用UDP作为底层传输协议。QUIC提供了等价于HTTP/2的多路复用和流控,等价于TLS的安全机制,及等价于TCP的连接语义、可靠性和拥塞控制。据国际互联网工程任务组(TheInternetEngineeringTaskForce,简称IETF)消息,HTTP-over-QUIC实验性协议将被重命名为HTTP/3,并有望成为HTTP协议的第三个正式版本。本文讲介绍QUIC协议在CDN技术上,在腾讯某战略级应用上的落地,以及相比于TCP所带来的极快的优化体验,并尝试分析QUIC到底快在哪里?背景在现有物理资源的情况下,CDN海外机房回源、回传延迟较高,RTT最高有几百毫秒,TCP丢包率和成功率表现也不尽人意,一个大视频分片的上传下载需要几秒时间。而QUIC的特性在网络传输,尤其是弱网情况下,效果相比TCP好很多。多段256NACK、更加激进的LossDetection丢包探测和重传机制、以及0-RTT的握手建立,使其相比TCP的传输延迟大大降低。1.封装QUICClientSDKQUIC运行在用户空间,底层使用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、多路复用、LossDetecion、流量控制、拥塞控制等等,非常复杂。所以在工程实现上我抽取了chromium的net库等重载QuicStream、QuicSession等,封装成易于理解的QUICClientSDK,提供quic_socket、quic_connect、quic_send、quic_recv等开发者比较习惯的socket使用方式API。图1.QUICClientSDK2.QUICClient在MCP++框架上的应用MCP++框架主要是DCC模块负责对外的请求下载等,在CDN上的应用的话,Front节点的回源、回传都需要通过DCC去下载和上传。◎QUIC由于其复杂的特性实现,运行在应用层的协议栈,需要大量的CPU计算。◎以及QUICClient自成一体的UDPSocket收发,DCC原本的epoll_wait单线程模型无法支持,很难改造。故而决定采用【DCC线程+QUIC线程】的模型支持QUIC协议,QUICClient线程保持高度的自治,请求与响应皆自我完善。DCC原本的连接管理,CRawCache等需要自己实现。图2.MCPDCC与QUIC交互如图2所示,DCC与QUIC交互主要有两个流程,不破坏现有DCC框架:1、send_mq_request_by_quic负责将来自mq的请求发给QUIC,由quic创建UDPsocket发送出去。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;发送和接收两种场景,分为发送失败和接收失败。图3QUIC请求与回退流程DCC->QUIC请求流程:1.epoll_wait接收来自MCD的管道mq事件。2.判断请求QUICorTCP,用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()发送数据:发送成功,SUCCESS流程结束,异步等待queue响应。发送失败,flow连接回退到TCP,当前请求消息通过TCP重试。Streambusy,QUIC所有Stream都处在忙状态,连接不回退,只有当前请求使用tcp发送。图4DCC接收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-RTTQUIC比TCP快的一个很大特点是其握手使用了更少的RTT,甚至达到0-RTT握手,直接进行数据传输,相比TCP大大减少了三次握手的等待时间。而我们在该战略级应用更进一步,front->zone的分布式集群所有机器之间的请求,除了第一次,以后均可以实现0-RTT建链。图5.QUIC0-RTT背景:QUIChandshake握手阶段服务端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进行下次握手,就会直接发起fullCLHO消息。服务端那边校验server_config通过,就能建立新的连接了。5.QUIC对比TCP的优化效果线上灰度观察效果,QUIC优化效果明显。尤其是在弱网下,传输时延大大降低:地区TCP回源&回传UDP回源&回传回源优化率回传优化率长沙电信秒级毫秒级59.8%25.4%美国OC2秒级毫秒级73.9%75.7%a)、国内以长沙电信为例,回源延时大幅度降低,优化效果能达到59.8%,回传原本延时就比较低了,延时优化效果也能达到25%。b)、海外以美国节点为例,QUIC的回源回传效果更加明显,优化率分别达到73.9%和75.7%。6.QUIC快在哪里?QUIC的提升效果表现如此的好,究竟比TCP快在什么地方呢?TCP协议经过几十年的发展,可以说构建了整个互联网的基础。Google为了开发QUIC做了很多工作,基本上把整个TCP的协议栈都重新实现了一遍(取其精华,修复缺陷)。尝试分析一下:1.0-RTTTCP的三次握手带来必定的1-RTT消耗,在网络状况比较好的情况下,大部分的消耗可能都来自业务,不觉得RTT耗时很多。但是在网路状况差的情况下(比如上面的美国),1个RTT就带来196ms的延时,使用QUIC优化后,可以看出整体耗时只有339ms,所以0-RTT对于秒开业务来说是一个很重要的特性。2.QUICStream多路复用—TCP队头阻塞QUIC支持多路复用,QUIC的底层UDP不进行排序和确认,只负责传输,ACK、确认、排序等都在QUIC进行。TCP当有多个流同时传输时,如果某个流发生了丢包,其他流需要等待其重传排序完成才能继续传输,因为TCP的滑动窗口只有一个,队头阻塞无法避免。而QUIC的多个Stream之间重传、排序等互不干扰,有stream级别的流控窗口,真正从传输层解决队头阻塞的问题。从应用的统计上看到,同一连接多个Stream同时传输的场景非常频繁。而去除了队头阻塞的QUIC延时比TCP低就很明显了,并且在弱网丢包率高场景下,表现更好。3.Upto256NACKranges,支持256分段ACKTCP每次只会ACK一个数据包,当滑动窗口用尽之后,只能等待新的ACK到来才能继续发送新数据包。就算开启了SACK,最多也只能ACK三个包。QUIC最大支持ACK256个数据包,支持分段ACK。就算某个ACK包丢失,后续其他包的ACK也能带上之前ACK过的包号。4.LossDetection丢包探测QUIC在TCP的经验之上重新构建了一种新的丢包探测机制:FR快重传、ER早期重传、RTO、TLP、F-RTO,和TCP相比很大不同。表现为更为激进的丢包发现和重传策略:比如如果收到最大的ACK包号大于3就判断丢包进行FR重传;而TCP需要收到连续三个重复的ACK才判断丢包进行快重传。7.总结本文介绍当前主流的基于chromium的QUICClientSDK的架构,以及其在腾讯某战略级应用的MCP++框架上的工程落地。详细介绍了MCP++框架上的DCC+QUIC多线程lib方案,和QUIC回退到TCP的保障机制,另外简单介绍了下全面0-RTT在Front->zone上实现存在的问题和解决方案。通过在线上落地使用QUIC,与TCP相比,加速效果显著。QUIC拥有0-RTT、多路复用、256NACK等优秀特性,是一个潜力很大的技术。IETF已经将HTTPoverQUIC重命名为HTTP3,随着下一代HTTP3协议的普及,QUIC将应用的更加广泛。spring扫码关注收获更多~我知道你在看哟
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:28 , Processed in 0.870861 second(s), 27 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表