作者|威磊鑫鹏辰通CDN已经成为互联网的重要基础设施之一,越来越多的网络服务离不开CDN,它的稳定性也直接影响着业务的可用性。CDN容灾一直由美团SRE团队负责,端侧的解决方案和实践很少。本文结合美团外卖业务的具体实践,介绍一种在终端侧检测CDN可用性并进行自动容灾切换的方案。该方案可以有效降低业务对CDN异常的敏感度,提高业务的可用性,同时降低CDN运维压力。希望这个方案能够帮助或者启发被CDN问题困扰的同学。一、前言作为业务研发,你是否遇到过因为CDN问题导致业务图片加载失败、页面打开速度慢、页面布局乱、白屏等问题?你有没有遇到过某些地区CDN域名异常,导致业务中断,客户投诉不断。这时候,你是手足无措,不知所措吗?作为CDN运维,您是否经常被业务方反馈的各种CDN问题搞得焦头烂额,一边顶着各种催促和压力寻求解决方案,一边抱怨服务商不靠谱?今天主要介绍美团外卖技术团队的端侧CDN容灾方案。经过实践,我们发现这款产品可以有效降低运维和业务开发同学的焦虑感。希望我们的经验也能帮助到更多的技术团队。2、背景CDN之所以成为互联网不可或缺的一部分,是因为它可以有效解决由于分布、带宽、服务器性能等原因导致的网络访问延迟等问题,也是前端业务非常依赖的服务之一。在实际业务生产中,我们通常会将大量的JS脚本、CSS资源、图片、视频、音频等静态资源托管到CDN服务中,通过其边缘节点缓存来享受静态资源的加速。然而,在享受CDN服务带来更好体验的同时,也时常受到CDN故障的影响。例如由于CDN边缘节点异常、CDN域名被ban等导致页面空白,布局紊乱,图片加载失败。每次出现CDN故障,业务方往往束手无策,只能寄希望于CDN团队。CDN的监控和排查对SRE来说也是一个巨大的问题和挑战。一方面,由于CDN节点分布广泛,边缘节点的监控难度极大。另一方面,各种业务聚合得到的CDN监控面板,在很大程度上隐藏了细节。小流量企业和定点区域的CDN异常,往往不堪重负。SRE团队也做了很多努力,设计了多种方案来降低CDN异常对业务的影响,取得了一定的效果,但是还有几个问题没有很好的解决:时效性:当有CDN的问题,SRE会手动进行CDN的切换,因为需要人为操作,响应时间很难保证。另外,无法准确保证切换后的故障恢复时间。有效性:切换到备份CDN后,无法验证备份CDN的可用性,并且由于LocalDNS缓存,无法解决域名劫持、跨网访问等问题。准确:CDN切换是大规模的变更,不能针对某个地区或某个项目独立进行。风险:切换到备份CDN后,可能导致回源,流量激增会拖累源站,造成更大风险。目前,美团外卖业务每天服务数亿人次。再小的问题在巨大的流量面前也会被放大成大问题。在外卖的动态架构中,70%的业务资源依赖于CDN,因此CDN的可用性严重影响外卖业务。如何更有效的实现CDN容灾,降低CDN异常对业务的影响,是我们不断思考的问题。既然在SRE端无法完美解决以上问题,那么是否可以在端侧做一些尝试呢?比如前端CDN容灾到终端侧。Phoenix(凤凰)就是在这个假设下通过前端能力建设不断实践和完善的一套端侧CDN容灾解决方案。该方案不仅可以有效降低CDN异常对业务的影响,还可以提高CDN资源加载的成功率。现已服务于整个美团的多个企业和应用。3.目标与场景3.1核心目标是降低CDN异常对业务的影响,提高业务可用性,减轻SRE同学在CDN运维方面的压力。切换:当CDN异常时,端侧检测并第一时间自动切换CDN域名进行加载重试,减少对人为操作的依赖。CDN域名隔离:CDN域名与服务商实现区域维度的服务隔离和等价服务,保证CDN切换重试的有效性。更精准有效的CDN监控:构建更细粒度的CDN监控,可按项目维度实时监控CDN可用性,解决SRECDN监控粒度不够、告警滞后等问题。并根据灾备监控动态调整CDN灾备策略,减少SRE切换CDN的频率。域名持续热备份:保证每个CDN域名持续预热,避免流量切换时回源。3.2适用场景适用于所有依赖CDN,希望降低CDN异常对业务影响的端侧场景,包括Web、SSRWeb、Native等技术场景。4、对于Phoenix方案,CDN的稳定性一直由SRE来保障,并且在SRE端进行了容灾措施。但仅靠链路层面的保障,难以处理局部问题,实现快速止损。用户终端作为服务的最终交付载体,具有天然的独立性和对资源负载的敏感性。如果把CDN容灾前置在终端侧,那么及时性和准确性是SRE侧无法比拟的。在设备侧进行容灾,需要感知CDN的可用性,进而实现设备侧和侧侧自动切换的能力。我们调研了整个前端领域,发现业界在端侧CDN容灾方面没有任何实践和产出,所以整个方案的实现是一个从零开始的过程。4.1总体设计图1Phoenix设备侧CDN容灾解决方案主要由五部分组成:设备侧容灾SDK:负责设备侧资源加载感知、CDN切换重试、监控和上报。动态计算服务:根据端侧SDK上报的数据,按照城市、项目、时间段等维度,定期轮询多个等效域名的可用性,动态调整流量至最优CDN。它也是CDN可用性的日常检查。容灾监控平台:从项目维度和市场维度提供CDN可用性监控和告警,为故障排查提供详细信息。CDN服务:提供完善的CDN链接服务,在架构上实现域名隔离,为业务方提供对等的域名服务,保证端侧容灾的有效性。等效域名是指可以通过相同路径访问相同资源的域名,例如:cdn1.meituan.net/src/js/test.js和cdn2.meituan.net/src/js/test.js可以返回相同的内容,则cdn1.meituan.net和cdn2.meituan.net是等价域名。灾备配置平台:配置管理项目灾备域名,监控上报策略管理,提供人工干预CDN流量等措施。4.2容灾流程设计为了保证各终端容灾效果和监控指标的一致性,我们设计了统一的容灾流程。整体流程如下:图24.3实现原理资源主要是JS、CSS和图片,所以我们的容灾目标也集中在这些上。Web端的容灾,我们主要针对静态资源、异步资源、图片资源进行容灾。实现思路要实现资源容灾,最重要的问题是感知资源加载结果。通常我们会在资源标签中添加一个错误回调来捕获它。这种方式可以实现镜像容灾,但是这种方式不适合JS,因为它有严格的执行顺序。为了解决这个问题,我们用XHR代替了传统的用标签加载资源的方式。在项目构建阶段使用Webpack提取同步资源,然后使用PhoenixLoader加载资源。这样就可以通过网络请求返回的状态码来感知资源加载的结果。在方案实现中,我们将SDK设计为WebpackPlugin,主要基于以下四个方面的考虑:通用性:美团前端技术栈比较多,需要保证容灾SDK能够覆盖大部分的技术框架。易用性:过高的接入成本会增加开发人员的工作量,业务无法有效覆盖,解决方案的价值无从谈起。稳定性:解决方案应保持稳定可靠,不受CDN可用性的干扰。侵入性:不能侵入正常业务,必须即插即用,保证业务稳定。通过研究发现,70%的前端工程建设都离不开Webpack,而WebpackPlugin独立配置,即插即用,是实施方案的最佳选择。整体方案设计如下:图3当然,很多团队在做性能优化的时候,会采用代码切分,按需导入的方式。这些资源在同步资源的生成过程中是无法感知的,但是这些资源的加载结果也关系到业务的可用性。在异步资源的容灾方面,我们主要是重写了Webpack的异步资源处理方法,使用PhoenixLoader来接管资源加载,从而实现异步资源的容灾。整体分析流程如下图所示:图4CSS资源的处理与JS的处理不同,但原理类似。只需要重写mini-css-extract-plugin的异步加载实现即可。Web端解决方案资源加载示意图:图5.容灾效果。图6.灾难恢复磁盘。Native侧的容灾建设也主要围绕上述资源展开。重新请教思路是Native-sideCDN容灾方案的基本原则。Native容灾基础设施容灾域名根据相互备份的CDN域名重新请求资源。整个过程发生在原始请求失败之后。原生容灾基础设施不会在原始请求期间执行任何操作,以避免影响原始请求。原请求失败后,Native容灾基础设施代理返回失败,业务方还在等待结果。重新请求完成后,将最终结果返回给业务方。整个过程中,从业务方的角度来看,只发送一次请求,一次收到结果,达到业务方不感知的目的。为了最大化重新请求的效率,需要保证重新请求的次数尽可能地趋向于最小化。研究业务侧重点和技术层面使用的网络框架,结合凤凰灾备解决方案的基本流程,在方案设计上,我们主要考虑以下几点:便捷性:访问的便捷性是第一位的SDK设计时的考虑,即业务方能够以最简单的方式接入,实现资源容灾,同时SDK能够简单无残留地移除。兼容性:Android端的特殊性在于网络框架的多样性,包括Retrofit框架、okHttp框架、okHttp3框架以及很少用到的URLConnection框架。提供的SDK要兼容各种网络框架,同时即使业务方改变网络框架,也能以最小的成本实现容灾功能。iOS端考虑复用一个NSURLProtocol来拦截请求,减少代码冗余,实现初始化项的统一适配。可扩展性:需要在基本功能之上提供可选的高级配置以满足特殊需求,包括监控方面的特殊监控数据上报能力。基于以上设计要点,我们将Phoenix分为如下结构图,其中将整体容灾SDK拆分为两部分,Phoenix-Adaptor和Phoenix-Base。图8Phoenix-BasePhoenix-Base是整个Phoenix灾备的核心部分,包括灾备数据缓存、域名替换组件、灾备请求执行器(区别于原来的请求执行器)、监控器内部的四个功能对外不可见模块,包含一个外部访问模块,提供外部访问功能。灾备数据缓存:定期获取和更新灾备数据,产生的数据只会被域名替换组件使用。域名替换组件:连接容灾数据缓存、容灾请求执行器、monitor中心节点,负责匹配原始故障主机,过滤错误码,提供容灾域名给容灾请求执行器,提供monitor的详细数据副本灾难过程。容灾执行器:容灾请求的真正请求者,目前使用内部的OkHttp3Client,业务方也可以独立切换到自己的执行器。监控:分发灾难恢复过程的详细数据,并上报到内置数据盘。如果有外部自定义监视器,数据也会分发到自定义监视器。Phoenix-AdaptorPhoenix-Adaptor是Phoenix容灾的扩展适配部分,兼容各种网络框架。Binder:生成适合各个网络框架的拦截器,绑定到原始请求执行器上。Parser:将网络框架的Request转换为Phoenix内部执行器的Request,将Phoenix内部执行器的Response解析为外部网络框架的Response,从而达到适配的目的。灾备效果①业务成功率以外卖图片业务为例,对比安卓业务成功率(同版本7512,2021.01.17未开通凤凰灾备,2021.01晚上开通凤凰灾备.19).图9iOS业务成功率对比(同版本7511,2021.01.17未开启Phoenix容灾,2021.01.19晚上开启Phoenix容灾)。图10②外卖与美团图片的风险反应对比。CDN服务异常时,接入凤凰的外卖APP与未接入美团APP的图片成功率对比。图114.3.2动态计算服务端域名重试。域名加载资源失败后,会根据容灾列表依次重试,直到成功或失败。如下图所示:图12如果域名A出现大范围异常,设备端仍然会先重试加载域名A,这会导致不必要的重试成本。如何让资源的首次加载更加稳定和有效,如何为不同的业务和地域动态提供最优的CDN域名列表,这些都是动态计算服务要解决的问题。计算原理动态计算服务通过域名池与项目的appkey关联,按照不同省份、不同地级市、不同项目、不同资源等维度进行策略管理。通过在5分钟内获取相应项目上报的资源加载结果,并定期轮询计算,按地区(城市&&省)监控域名池中域名的可用情况。计算服务会根据域名可用性动态调整域名顺序并输出结果。下图是一个完整的计算过程:图13假设有A、B、C三个域名,成功率分别为99%、98%、97.8%,流量占比为90%、6%,和4%。基于转移基准,进行流量转移。例如A和B的成功率之差为1,B需要将自己1/2的流量转移给A,同时如果A和C的成功率之差大于1、C还需要把自己1/2的流量转移给A,B和C的差0.2,所以C也需要把自己1/4的流量转移给B。最后经过计算,A的流量比例是95%,B的是3.5%,C的是1.5%。最后,经过排序和随机计算后输出最终结果。因为A的比例最大,所以先选A;通过随机,B和C也会有一定的流量;基于转移基准,可以实现流量的平??滑切换。当CDN因异常无法正常访问时,CDN访问流量会通过计算过程切换到对等的CDNB。如果SRE发现切换太慢,可以手动介入分配流量。当少量A域名的成功率增加时,会重复计算过程来增加A.的流量,直到恢复初始状态。图14服务效果动态计算服务首次将资源加载成功率从99.7%提高到99.9%。下图是访问动态计算后的资源加载成功率与未访问时的资源加载成功率对比。图154.3.3灾备监控在监控层面,SRE团队往往只关注域名、大地域、运营商等多个维度的监控指标。监控流量巨大。对于小范围的小流量服务或CDN波动,可能检测不到。监控、分析、识别,让CDN边缘节点的异常无法感知。灾备监控的建设主要是解决CDN监控告警滞后和SRE团队监控粒度的问题。监控的总体设计如下:图16为端侧灾备数据上报的流程设计,按照项目、APP、资源、域名等维度建立监控指标,并使CDN可用性是项目可用性的一部分。通过计算平台对数据进行分析聚合,形成CDN可用性市场,按域名、地区、项目、时间等维度输出,与天网监控互通,建立分钟级监控告警机制,大幅提高灵敏度CDN异常感知。同时,SRE端的天网监控也会干扰动态计算服务的结果。整体监控流程如下:图17监控效果CDN监控不仅从项目维度更细粒度地监控CDN可用性,还为CDN异常排查提供更丰富的区域、运营商、网络状况、返回码等信息.在监控告警方面,实现了分钟级异常告警,灵敏度也高于美团内部监控系统。图184.3.4CDN服务器端域名切换的有效性离不开CDN服务的支持。CDN服务方面,在原有SRE侧容灾的基础上,对CDN服务进行整体升级,实现域名隔离,解决了单个域名对应多个CDN、多个CDN的重试无效的弊端。一个CDN对应的域名。图195总结与展望经过一年的建设和发展,凤凰CDN容灾解决方案日趋成熟,成为美团唯一的CDN容灾公共服务,在众多CDN异常中发挥了巨大的作用。在终端侧,该方案目前日均灾备资源3000万+,恢复用户35万+,覆盖外卖、酒旅、餐饮、优化、买菜等业务部门,服务200+项目、外卖App、美团App、大众点评App已接入。在SRE端,实现了项目维度的分钟级精准告警,同时丰富了异常信息,大大提升了SRE排查效率。由于该方案大规模实施,CDN异常时很少进行手动切换操作,大大减轻了SRE同学的运维压力。由于前端技术的多样性和复杂性,我们的SDK无法涵盖所有??的技术方案,所以在接下来的建设中,我们会积极推广我们的容灾原则,开放动态计算服务,希望更多的框架和服务在我们的容灾中恢复思维,我们结合自身业务实现端侧CDN容灾。此外,对于方案本身,我们将持续优化资源加载性能,完善资源签名校验、智能切换等能力,欢迎对凤凰CDN灾备方案感兴趣的同学与我们共同探讨交流。同时,欢迎加入我们,招聘信息附在文末,期待您的来信。6.作者简介魏磊、陈彤、张群、岳军等均来自美团外卖平台-大前端团队,丁磊、鑫鹏来自美团餐饮SaaS团队。
