AI知识库

53AI知识库

学习大模型的前沿技术与行业应用场景


Ray 在微信 AI 计算中的大规模实践

发布日期:2025-02-15 13:05:49 浏览次数: 2002 来源:DataFunTalk
推荐语

微信AI计算如何实现大规模服务?Ray技术在其中扮演了哪些角色?

核心内容:
1. 微信AI计算服务的背景及需求
2. Ray技术在百万级节点集群管理中的应用
3. 如何降低AI算法服务的部署复杂度

杨芳贤
53A创始人/腾讯云(TVP)最具价值专家


导读 本文将探讨 Ray 在微信 AI 计算中的大规模实践。

主要围绕下面六点展开:


1. 背景

2. 百万级节点的集群管理

3. 高效稳定的利用低优资源

4. 降低应用部署复杂度

5. Astra-Ray 使用样例

6Q&A

分享嘉宾|陈国敏 腾讯 微信专家工程师,微信 Astra 平台负责人

                  苏文豪 腾讯 微信高级工程师

编辑整理|马同学

内容校对|李瑶

出品社区|DataFun


01

   背景



微信现在已经成为人们日常生活中非常重要的组成部分,而随着人工智能的发展,微信内也为用户提供了多种涉及 AI 计算的服务体验。例如,语音消息的文字转换、视频号的 AIGC 和推荐、扫一扫功能的图像识别等。这些功能由于微信的用户规模巨大,所以 AI 计算的服务规模也非常大。


为了应对大规模的 AI 计算任务,我们建立了 Astra 平台,目前,有许多业务已经接入了 Astra 平台,这些业务在平台上构建了众多 AI 算法服务,覆盖了 LLM/多媒体处理等多个方面。



目前我们对于 Ray 的使用场景主要是 Ray Serve,在 Astra 平台之前,我们团队是一个纯粹的后台开发团队。因此在我们在实际工作中,会更加深入的思考 AI 算法服务与传统微服务之间的区别。


首先,关于应用规模,传统的微服务一般最多只有几千个节点、十来万核。然而,在AI算法这种计算密集型的任务上,我们的 AI 算法服务往往需要数十万节点,其计算资源需求可达数百万核。这种超级应用对我们的模块管理系统以及 K8S 集群提出了极高的要求,要支撑如此大规模的应用部署是非常困难的。


其次,随着资源数量和资源种类的增加,部署复杂度快速升高。AI 算法服务对 GPU 资源有特殊需求,市场上存在多种类型的 GPU,例如 NVIDIA、紫霄、昇腾等品牌。这些不同型号的 GPU 需要特定的适配工作,这无疑增加了每次部署时的复杂性和工作量。


再者,运维难度亦不容忽视。微服务主要涉及业务逻辑,不存在复用性,但 AI 算法是一种纯算法服务,并不存在业务逻辑,不同的业务可能都会需要分别部署独立的集群,这也相应地提高了运维工作的复杂程度。


最后,成本问题同样突出。当前 GPU 的价格高昂,算力资源十分昂贵。降低 AI 推理的成本并提高资源利用率也是我们的重要目标之一。


鉴于上述考虑,我们选择了 Ray。它可以提供统一的分布式平台,整合多种计算模式,构建一个完整的生态系统。


早在 2022 年,我们就注意到 Ray 的优势,当时对于 Ray 的理解尚浅,但观察到国内外众多企业,包括 ChatGPT 等先进应用的成功案例,我们决定加大对 Ray 的投入,利用其将单机应用轻松扩展至分布式环境的能力,简化我们的开发流程,并实现更高效的资源管理。



接下来介绍 Astra 平台与 Ray 结合的整体架构。在这一架构中,平台管理的基本单位是基于 Ray 的应用,其底层由我们自主设计的联邦集群架构支撑。该架构底层连接至公司内部多个 K8S 集群,允许我们的应用部署于不同的 K8S 集群之上。这些 K8S 节点是我们预先从 K8S 申请的资源,每个节点上都会集成我们 Starlink 集群管理的 Agent、网络穿透 P2P 下载组件以及 TFCC AI 运行时。


架构图的下层展示了 Starlink 集群管理模块,它主要提供了以下几项核心能力:服务发现、负载均衡、容灾调度以及应用调度。面对的主要挑战是支持多达数十万个节点的大规模集群管理,这意味着我们需要具备处理百万级 Pod 节点的能力,并确保高效的集群管理。此外,为了降低成本,考虑到腾讯内部可能存在资源利用不充分的情况,我们致力于优化资源配置,充分利用那些利用率较低或空闲的资源。最后,为了简化应用部署流程,我们为算法开发人员提供了便捷的方式,使他们能够迅速且轻松地部署应用程序。


通过这样的架构设计,我们不仅能够应对大规模集群管理带来的技术挑战,还能够在成本控制和部署效率上取得显著进步,从而更好地支持微信平台上的 AI 计算需求。



02


百万级节点的集群管理



接下来,将详细探讨在处理百万级节点集群管理时所面临的挑战及解决方案。


调度架构通常可以分为三种类型:单层、两层以及共享调度。每种架构都有其特点和适用场景。


单层调度:这种架构类似于 K8S,适用于规模较小的集群,一般为数千个节点。单层调度的一个主要限制是其较低的并发度,因为整个集群通常只依赖于单一的调度器进行资源分配。


两层调度:此架构预先将资源池中的机器分配给上层调度器,例如 Spark 采用的就是这种模式。相比单层调度,两层调度具有更高的并发度,支持更大规模的集群。


共享调度:这一概念源于谷歌的 Omega 论文。其核心特点是支持无限数量的调度器,每个应用都有自己的调度器,且所有调度器都能查看到整个资源池的状态。我们实现了乐观调度策略,即每个调度器假设没有冲突地分配资源,并在检测到冲突时进行调整。这种方法不仅能够显著提升调度规模和资源利用率,还能大幅提高调度并发度,非常适合处理数十万节点的大规模集群需求。


对于需要管理几十万甚至更多节点的超级应用而言,选择共享调度架构几乎是必然的。它通过允许多个调度器同时工作,确保了高并发度和高效的资源利用,满足了大规模集群管理的需求。我们的 Astra 平台结合 Ray,正是采用了这样的共享调度策略,以应对微信 AI 计算中遇到的巨大挑战。



接下来,将深入介绍 Astra 自研调度架构的整体设计,我们从下往上介绍。


最底层是部署在不同 K8S 集群上的节点,这些资源是预先分配好的。例如,特定业务可以向 K8S 申请所需的资源,并将其集成到我们的平台中使用。每个 K8S 集群包含各自的节点,这些节点会定期向 resource 集群发送心跳信号,以报告其状态。


Resource 集群会聚合这些心跳信息,并通过广播的方式实现轻量级的状态同步。这一机制保证了即使单个集群仅由几台机器组成,也能够支持多达百万级别的节点管理,并维持一个在线节点列表,作为高性能资源管理的基础。


Resource 是整个系统的核心部分,它不仅负责收集和同步节点状态,还提供了高效的资源管理能力。Resource 集群能够实时掌握所有节点的最新状态,为上层调度提供准确的信息。


在 Resource 集群之上,是 APP 级别的独立调度器。每个应用程序(APP)都有自己的调度器,这些调度器可以直接访问整个集群中所有节点的状态信息。每个调度器的主要职责包括:资源调度、负载均衡、容灾调度。得益于共享调度的设计,调度器每分钟可以处理数万节点的调度任务,极大提升了系统的响应速度和效率。


最上层是用户操作界面,用于执行诸如扩缩容等操作。这一层直接与最终用户交互,提供了直观的操作体验,使得用户可以轻松管理其应用程序和服务。


这套架构构成了我们进行百万级别集群管理的基础,通过分层设计和资源共享调度机制,实现了对大规模节点的有效管理,同时保证了高并发度和资源利用率,满足了微信 AI 计算中的复杂需求。此架构不仅支持了数十万节点的大规模集群管理,还显著降低了运维复杂度和成本,提高了整体的服务质量和用户体验。



03


高效稳定地利用低优资源



下面探讨如何高效且稳定地利用低优资源。腾讯内部低优资源的总量非常庞大,但与此同时也伴随着诸多挑战,“天下没有免费的午餐”,尽管低优资源的成本较低,但也带来了新的问题。


以下是从我们系统监控中截取的几张图,能说明我们所遇到的一些问题。


首先,节点处于亚健康状态的比例较高,例如 CPU 时间片可能会被抢占,或者节点可能随时被高优先级任务抢占。在 Ray 的应用上,当 Ray 应用部署到低优资源时,节点被抢占会导致集群难以恢复。特别是在 Ray Cluster 错误处理方面,如果头节点出现故障,会难以恢复。当前社区版仅提供通过 Redis 备份的方式进行恢复,但我们不希望在服务中引入额外的依赖。因此,我们希望有一种简洁的解决方案,能快速的地解决这一问题。



针对亚健康节点及被移除节点的快速处理,我们采取了一系列措施以确保系统的高效与稳定。以下是具体方法:


首先,对于异常节点的下线,K8S 平台通常不会提前很长时间通知即将缩容。因此,我们使用 K8S 的 Pre Stop 特性来迅速响应。由于我们的心跳检测频率为每秒一次,一旦触发 Pre Stop,我们可以立即从在线列表中移除该节点。在3秒钟内更新路由表,这意味着在 Pre Stop 触发后的 4 秒内,该节点将被完全移除。即使节点随后被资源平台直接终止,也不会对我们的服务造成影响。


其次,对于性能较低的节点,我们会实时监控并收集其运行数据。通过自动调节权重的路由算法调整节点接收的请求量。具体而言,性能较差的节点将被赋予较低权重,而高性能节点则保持较高权重。这种机制确保了任务能够根据节点的实际性能进行合理分配,从而优化了 serving 层的工作负载分配,优化了整体服务吞吐和耗时。


通过上述措施,我们不仅能够快速处理异常节点,还能有效管理性能差异较大的节点,确保系统在面对低优资源固有问题时仍能保持高效稳定的运行。



从我们在 Astra 平台上使用低优资源的效果图中可以清晰地看到优化前后的对比。图中的绿色线条代表优化之前的状态,而红色线条则展示了优化之后的结果。通过对比可以看出,优化后我们的失败率显著降低,同时平均处理时间也得到了大幅改善。



在低优资源上使用 Ray 时,我们必须良好的设计系统来容忍节点(包括 worker 和头节点)被频繁踢出的情况。为此,我们借鉴了 K8S 联邦集群的概念,提出了 Ray 联邦集群的架构。这一架构的核心特点是每个 Ray cluster 作为一个服务的最小单位,每个 Ray Cluster 都能够独立提供完整的服务。这种设计确保了即使任意一个 Ray cluster 出现故障,整体服务依然不受影响。


Ray 联邦集群的特点包括:


  • 服务单元化:每个 Ray cluster 都是一个独立的服务单元,可以单独提供完整的服务。



  • 容灾能力:通过增加更多的 Ray cluster 来实现容灾。每个 cluster 都可以视为一个容灾单元,从而增强了系统的鲁棒性。



  • 突破规模限制:由于我们的基础设施本身支持百万级节点管理,我们可以将每个 Ray cluster 设计得较小,从而突破单个 cluster 的规模限制。



  • 无状态服务般的容灾:无论哪个节点或整个 cluster 挂掉,我们都可以迅速替换,确保服务的连续性。



具体容灾方案如下:


  • 头节点故障处理:当头节点出现心跳异常时,我们会立即从路由算法中移除该 cluster,并调度一个新的 Ray cluster 进行替换。



  • Worker 节点故障处理:如果仅是 worker 节点故障,该 cluster 仍可继续使用,只需替换故障的 worker 节点即可。



  • 扩展性:我们的 Ray Cluster 机制支持纵向扩容,可以根据需要调整 worker 数量,从而解决了大规模部署下的扩展性问题。



通过上述措施,我们不仅提升了系统的容灾能力,还确保了在大规模节点管理中的高效性和灵活性。此架构使得每个 Ray APP 可以拥有无数个请求者,集群能够像无状态服务一样灵活应对节点或 cluster 级别的故障,确保了服务的高可用性和稳定性。



针对训练任务的自动调速,我们开发了一套内部工具用于数据处理。鉴于低优资源随时可能被移除,这会导致集群处理能力下降,我们对每个节点的性能进行了预估,即根据资源类型和数量来评估其处理能力。随着集群资源指标的变化,我们会自动调整任务的消费速率,以确保服务的正常运行。自动调速机制如下:


  • 性能预估:我们根据资源类型(如不同型号的 GPU)和可用资源的数量,动态评估每个节点的处理能力。这一预估考虑了多种卡型共存的情况,确保评估结果的准确性。



  • 动态调整消费速率:基于性能预估的结果,当检测到集群中的资源变化时,系统会自动调整任务的消费速率。这种调整确保即使在资源减少的情况下,也能维持服务的稳定性和性能。



  • 保障服务连续性:通过上述机制,即使低优资源被移除或集群处理能力发生变化,我们的系统仍能保持正常运行,避免因资源波动导致的服务中断。



通过这套自动调速机制,我们的离线任务可以稳定的在低优资源上进行部署,确保了在复杂多变的环境中,离线任务能够持续高效地运行。



04


降低应用部署复杂度



接下来探讨如何降低应用部署的复杂度。一个 APP 可能包含多个模型,每个模型需要部署在不同类型的 GPU 上,且每种 GPU 类型可能会超出系统单个集群的数量、规模限制。这种情况下,我们面临的复杂度大约是 O(N^3)。为了有效降低这一复杂度,我们采取了以下措施:


首先,多模型扩展。我们选择 Ray 作为解决方案的关键原因之一在于其能够简化多模型扩展。以往,服务中可能需要引入一个中间模块来专门管理各个模型之间的调用。而现在使用 Ray,仅需一个脚本即可实现多模型的有效管理和调度,大大简化了部署流程。


其次,多卡型扩展。针对不同类型的 GPU,我们设计了相应的扩展机制。这部分内容将在后续详细说明。


最后,多模块扩展。我们的架构还支持多模块的扩展,确保系统能够灵活应对不同类型和数量的组件需求。


通过上述措施,我们显著降低了应用部署的复杂度,使得多模型、多卡型以及多模块的管理变得更加高效和简便。



接下来我们详细描述我们如何做到这一点。首先,统一基座环境。


  • 核心组件:该环境包含了所有必需的核心组件,例如 P2P 网络穿透、TFCC 以及特定版本的 CUDA,以确保一致性和兼容性。



  • 包管理:允许用户使用 Conda 管理包,允许用户选择不同版本的 Python,并实现自定义环境配置。这一系统是我们自行开发的环境管理工具,旨在为用户提供灵活的包管理能力。



  • 自定义库与编译:支持用户自定义使用各种库及进行 CI(持续集成)编译操作,以满足多样化的开发需求。



其次, TFCC 引擎的支持。


针对不同类型的 GPU(如 NVIDIA、昇腾等),特别是当 NVIDIA 卡用于 TensorRT 时可能需要不同的模型编译,TFCC 引擎起到了关键作用,它能够屏蔽底层 GPU 卡的具体类型,使得用户无需关心底层硬件细节。用户只需调用 TFCC 提供的推理接口,即可完成推理任务,无论底层使用何种 GPU 卡。


通过上述标准化的环境管理方案,不仅简化了多依赖项的服务部署,还确保了跨多种 GPU 类型的无缝支持,极大提升了用户体验和服务灵活性。



最后是 P2P 下载优化。随着 AI 模型规模的不断扩大,正如前面提到当前的模型体积已经显著增加。例如,一些常见的 72B 模型可能达到 140GB 的大小。将如此庞大的模型下发至各节点进行部署耗时会比较长。为此,我们使用 P2P 对下载能力进行了多项优化:


  • NAT 穿透:实现了 NAT 穿透功能,确保在复杂网络环境下也能高效传输数据。



  • 节点限速与全局限速:为保证网络资源的合理分配,引入了节点级别的限速和全局限速机制。



通过这些优化措施,我们现在能够将一个大约 140GB 的模型在大约 10 分钟左右的时间内完成下发。这大大缩短了模型部署的时间,提高了整体工作效率。



05


Astra-Ray 使用样例



下面是在平台上的一些截图,帮助大家了解我们平台的使用界面和部署流程。以下是具体步骤:


第一步是修改代码,只需要按照 ray serve 做简单的改写即可。


第二步是将修改后的代码打包并上传至 Git 仓库。在此过程中,需要选择一个 Python 版本。平台会根据选择自动打包,生成一个可以在我们平台上运行的部署包。



第三步是变更 Ray 配置,这实际上是调整服务的 deployment 配置。此步骤允许用户通过配置变更来动态调整服务参数。考虑到在线服务的稳定性,我们设计了灰度发布机制。为了确保配置变更能够平稳生效,而不对现有服务造成即时冲击,用户可以通过灰度发布的方式逐步应用新的配置。这种方式允许新配置在一部分流量中先行验证,确保其稳定性和兼容性后再全面推广。通过这一机制,用户可以在不影响整体服务的情况下,安全地测试和应用新的配置调整,从而保障了服务的连续性和可靠性。



第四步是进行扩容。完成扩容后,可以立即看到服务启动,并在平台页面上查看集群的机器列表。例如,展示的一个集群机器列表中,包含大约 4,000 多个请求者(requester),每个请求者对应 5 台机器,总计超过 2 万个节点。


此外,我们还提供了以下功能以支持更高效的管理和调试:


  • Ray Dashboard:用户可以通过 dashboard 查看请求的状态和性能指标。



  • 日志调试:平台支持日志记录和调试功能,帮助用户快速定位和解决问题。




06


Q&A



Q1:关于低优资源的抖动状态问题


问:您刚才提到的低优资源存在 3 秒更新路由表和每秒更新机制。对于一些状态不稳定的资源,例如其性能可能一会儿好一会儿坏,这种情况是否会引发抖动?这种不稳定状态是如何处理的?


答:理解您的问题,确实存在两种情况:


性能波动:当节点的 CPU 被压制时,可能会出现性能不稳定的情况。我们通过动态调整权重来应对这一问题,确保即使性能波动也不会影响服务的整体质量。


节点掉线与重启:如果一个节点突然掉线后重新启动,我们会将其视为一个新节点进行处理。若它快速重启,可能不会特别关注;但如果触发了 PreStop 机制,则该节点会被移除,并在重新上线时作为新节点加入资源池。


Q2:关于每秒更新频率的问题


问:每秒更新的频率是否过高?这是否会带来额外的压力?


答:每秒心跳确实会带来较高的请求量,尤其在面对数十万个节点时,会产生较高的 QPS 压力。为此,我们采用了聚合扩散机制来减轻集群负担。首先,我们要保证自身服务的性能;其次,在集群容量接近极限时,可以通过扩展更多集群来支持更大的规模。Starlink 架构并非局限于单一 Resource 集群,而是也可以灵活扩展至多个集群。


Q3:超级 APP 跨集群调度机制


问:超级 APP 如何实现跨多个 Ray Serve 的调度?是通过每个集群内部的调度器还是有更高层次的调度机制?


答:通过 RPC 的方式,不同 Ray 集群之间是不互通的,但是我们保证每个 Ray 集群都有完整的功能。


Q4:超级 APP 副本故障恢复机制


问:在一个超级 APP 拥有大量副本的情况下,如果部分副本挂掉,是由哪个调度器负责重启这些副本?


答:由 APP 自身的调度器负责维护其所有 Ray Serve 的状态。即便应用规模庞大,调度器也仅需定时扫描即可管理。假设一个超级 APP 有 100 万个集群,扫描一次也只需一秒钟左右的时间。因此,即使是超大规模的应用,其调度器也不太可能成为瓶颈。


Q5:联邦集群的逐步扩展与负载均衡


问:联邦集群是如何逐步扩展并淘汰旧集群的?特别是在进行版本升级时,如何保持负载均衡?


答:联邦集群的扩展和淘汰是一个渐进的过程。头节点并不执行具体的业务逻辑或 worker 任务,而是与 worker 等价,以减少对系统的影响。在做路由算法时,我们将所有节点视为等同,简化了管理和调度过程。


Q6:在线服务 Runtime 优化


问:是否在 Ray 的 runtime 层面进行了特定优化?


答:目前我们尚未对 Ray 框架本身进行修改。该项目从今年上半年开始引入 Ray,因此现阶段的重点在于集成而非深度定制。


Q7:TFCC 引擎的透明性与模型转换


问:实际使用者是否需要关注推理引擎的选择?模型转换和优化是如何处理的?


答:用户无需关注底层使用的具体推理引擎。我们在打包过程中将运行内容分为三个部分:软件包、环境包和数据集(通常是模型)。上传时,我们会对模型进行预处理,转换成适用于各种 GPU 卡的版本,并对其进行性能优化。这一切都是自动完成的,用户只需提供输入参数。


Q8:推理引擎通用接口


问:不同推理引擎的特性(如 Dynamic Batch、Attention 机制)是否通过通用接口封装?


答:当前并不是所有推理任务都使用 TFCC,但我们计划未来增加支持。最常用的接口只需要提供输入形状等基本信息。对于不同推理引擎的特性,我们正在考虑如何通过通用接口进行适配,但目前尚未完全封装。


Q9:Ray 联邦集群间的通信


问:腾讯内部的 Ray 联邦集群是否实现了分布式共享内存的打通?不同 Ray serve 之间是否可以直接通信?


答:不同 requester 之间的对象无法直接获取。要访问其他 requester 的对象,只能通过 API 接口进行间接访问。


Q10:TFCC 与显存管理


问:TFCC 是否实现了显存的分布式管理?


答:目前还未实现。


53AI,企业落地大模型首选服务商

产品:场景落地咨询+大模型应用平台+行业解决方案

承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业

联系我们

售前咨询
186 6662 7370
预约演示
185 8882 0121

微信扫码

和创始人交个朋友

回到顶部

 

加载中...

扫码咨询