本文指导你完成负载测试马赛克 AI 模型服务终结点的基本过程,以确保它们可以有效地处理生产工作负荷。 它还提供了实际示例、实际模拟以及使用 Locust 负载测试框架的分步说明,演示如何测量关键性能指标(如每秒请求数和并发限制),以便可以正确调整终结点大小,并自信地为业务需求部署模型。
什么是负载测试?
负载测试是一项测试,用于模拟马赛克 AI 模型服务端点的真实世界使用情况,确保它们满足您的生产需求,例如响应延迟或每秒请求数。 负载测试可测量终结点在不同流量级别下的性能,帮助你正确调整终结点的大小,以免造成延迟。
图为:一个工作日上午8:00,市中心一家受欢迎的咖啡馆刚刚开业。 新鲜咖啡的香气弥漫着空气。 咖啡师已准备就绪,咖啡机也已预热完毕,而门外,一群急需咖啡提神的顾客已经排起了长队。
起初,事情运行顺利。 几位顾客挺身而出,下订单,咖啡师开始准备饮料。 有些饮料需要30秒,而另一些则需要一分钟,这取决于饮料制作的复杂性。 咖啡师熟练地管理多个订单,展现了高效的处理技能。
但很快,更多的人到了。 最初有五个客户,增加到十个,然后再到二十个。 大家各自点着单,等着自己的那杯,或许还会在吧台前聊上几句。 咖啡师现在承受着压力。 即使第二位咖啡师开始帮忙,系统也开始出现压力——排队的人越来越多,订单堆积,顾客开始等待更长时间。
现在,想象一下你试图测量咖啡馆在顾客开始感到沮丧并离开之前每分钟可以供应多少饮品。 这是 负载测试。
在此类比中:
- 每个客户都是发送请求的 客户端 。
- 咖啡师代表你用于逐个或并行处理模型推理的服务器。
- 下订单和服务饮料的时间是 模型实施 时间。
- 通话、付款或查找订单的延迟是 网络开销。
- 更多同时到达的客户是客户端并发。
- 添加更多咖啡师或更多计算机就像增加 服务器并发一样。
和在任何好的咖啡馆一样,员工一次能处理多少,这是有限制的。 如果你不提前计划,例如在高峰时段安排更多的咖啡师,人们会感到不满。 同样适用于负载下的系统。 负载测试可帮助你确定瓶颈的位置、系统可以处理的流量以及为更流畅的服务做出哪些更改。
在终结点上运行负载测试之前,需要:
- 了解与负载测试相关的组件和概念。
- 决定并定义生产要求。
- 查找负载测试框架在对终结点进行基准测试时使用的代表性有效负载。
负载测试概念和定义
下表定义了负载测试相关的概念:
| 概念 | DESCRIPTION |
|---|---|
| 客户端并发(客户端数) | 同时向终结点发送请求的客户端总数。 在上面的示例中,这些是来咖啡馆的顾客。 生产:将流量发送到模型服务终结点的客户端的实例总数。 负载测试:在 Locust 中,这是创建的用户数,用于将流量发送到正在负载测试的模型服务终结点。 |
| 终结点并发 | 可以处理传入请求的推理进程或模型实例数。 还可以表示为终结点可以同时处理的请求的数量。 这是上述示例中的咖啡师的数量。 Mosaic AI 模型服务:可以为计算横向扩展配置模型服务终结点。 例如,使用 Small CPU 终结点的大小会在终结点上创建模型的四个实例。 |
| 延迟 | 完整往返请求完成的时间(以毫秒为单位)。 客户端在收到响应之前发送请求的总时间(包括终结点运行时和网络延迟)的度量值。 |
| PXX (P50,P90,P99) 延迟 | 该延迟值(以毫秒为单位)代表了这样一个时间点:有 XX 百分位的请求在此时间点之前完成(即耗时少于该值)。 例如,P90 的 30 毫秒意味着所有请求的 90% 在 30 毫秒或更短时间内完成。 |
| 每秒请求数(RPS) | 每秒完成的请求数。 Completed 表示响应从终结点返回给客户端。 |
延迟要求
根据业务需求和客户要求,定义系统的理想性能。 在提供终结点的模型上,延迟包括客户端在发送数据进行推理时体验的往返时间。 这包括网络延迟和推理时间。 请务必确保你的要求是现实的。 例如,如果模型被加载到内存时需要 15 毫秒来执行推理运算,那么在模型服务端点上处理时,还需要为网络延迟留出额外时间。
RPS、延迟和并发有何关联?
企业有一些定义的标准,用于评价其系统的成功。 对于 ML 系统,业务标准通常是高质量的结果、低延迟和高吞吐量。 结果质量与模型本身特别相关,而端到端延迟和吞吐量是服务系统的特征。 端到端延迟包括模型执行时间和网络开销。 吞吐量(或每秒请求或查询数)与延迟相反,与并发直接相关。
- 并发越高,吞吐量就越高。
- 延迟越高,吞吐量越低。
通常,对于任何给定的应用程序,客户端并发与服务器端并发的比率最佳。 例如,“一名厨师可以同时制作多少个汉堡”。 由于烹饪过程中可能有许多共享步骤,因此线厨师可能能够更优化地同时煎四个汉堡,而不是一个一个地煎。 这种并行化有限制,有时执行许多并行行为的行为会增加太多的延迟,就像厨师需要向 1000 个汉堡添加奶酪一样。
负载测试的核心目标之一是确定应用程序的最佳比率。 最佳比率将 RPS 最大化,满足延迟要求,并避免排队。 此比率可用于准确调整终结点的大小,以满足最苛刻的负载。
如果终结点无法足够快地处理请求,则会开始形成一个队列。 这称为队列。 队列的形成通常会导致更长的端到端延迟,因为现在,每个请求在处理之前等待的时间都会增加。 如果请求的到达速度比可以处理的请求快,队列就会增长,从而进一步增加延迟。 因此,必须了解您的终端可能会遇到的峰值需求,并通过负载测试确保合理规划其容量。
负载测试方案示例
在负载测试以及实际系统中,客户端并发、服务器并发和延迟之间的关系是动态和相互依赖的。 让我们通过一个简单的示例来查看此关系:
方案 1:简单设置
在此设置中,单个客户端按顺序发送请求 , 它会在发出下一个请求之前等待响应。 由于每个请求的总时间是模型执行和开销延迟(40 毫秒 + 10 毫秒),因此测量的端到端延迟为 50 毫秒。
- 客户端数:1
- 预配的并发:1
- 额外延迟:10 毫秒
- 模型执行时间 40 毫秒
因此,客户端每 50 毫秒完成一个请求,相当于每秒 20 个请求或每秒查询数。
方案 2:增加预配的并发
在这种情况下,预配了双倍的并发,并且由一个客户端按顺序发出请求。 这意味着总延迟仍为 50 毫秒(40 毫秒 + 10 毫秒),并且系统仅看到每秒 20 个请求(QPS)。
- 客户端数:1
- 预配的并发:1 -> 2
- 额外延迟:10 毫秒
- 模型执行时间 40 毫秒
方案 3:向系统添加另一个客户端。
现在,有两个客户端向具有两个预配并发的终结点发出请求。 在这种情况下,每个客户端的请求都可以由终结点同时独立处理(假设完全负载均衡)。 因此,尽管总延迟仍为 50 毫秒(40 毫秒 + 10 毫秒),但系统每秒观察 40 个请求,因为每个客户端发送 20 个 qps。
- 客户端数: 1 -> 2
- 预配的并发:2
- 额外延迟:10 毫秒
- 模型执行时间 40 毫秒
通过提升预设的并发数和发出请求的客户端的数量,可以提高系统中观察到的总 QPS,且不会带来额外的延迟损耗。
方案 4:减少预配的并发
在此最后一个场景中,客户端数量大于预配置的并发量。 此设置在系统中引入了另一个变量、队列及其对 QPS 和延迟的影响。
- 客户端数:2
- 预配的并发:2 -> 1
- 额外延迟:10 毫秒
- 模型执行时间:40 毫秒
在这里,你有两个客户端同时发出请求。 但是,终结点一次只能处理一个请求。 这会强制第二个请求在处理第一个请求之前等待。 第二个请求的等待(更准确地说是“排队”),可能会对系统延迟产生负面影响。 假设服务器允许排队(在 Databricks 模型服务中默认启用),第二个客户端看到延迟为 90 毫秒:10 毫秒(网络开销) + 40 毫秒(队列等待时间) + 40 毫秒(模型执行时间)。 这明显比之前看到的 50 毫秒差得多。