用Koi池塘装载测试

2021-06-10 19:08:48

复杂的系统难以在规模上推理;我们常常无法准确推断系统行为和性能,因此我们需要经验派生数据。我们使用负载测试来做到这一点:在受控环境中以大规模的大规模查找我们的系统的限制和杂草。 Slack是一个非常复杂的系统 - 无论您是触发数千个成员的工作流程还是将文件上传到一个线程,一切都是互连的!为我们的用户提供发送信息并立即出现在可能数百万客户中的经验所需的技术非常具有挑战性,以便在规模中建立和测试。为了充分加载测试我们的系统,我们需要构建一个工具,它在镜像实际用户流量和行为时都是现实和成本效益的工具。

向我们的WebApp后端发送API请求。这也可以在我们的作业队列中启动异步作业。

通过WebSocket连接发送和接收实时事件(例如,呈现更改和诸如用户键入的事件)。详细了解我们的WebSocket消息在此博客文章中的工作。

作为一个例子,发送信息的看似简单的行为经历了很多旅程。首先,连接的客户端调用Web API Chat.PostMessage。这将发送到我们的后端,该后端查询我们的实时服务堆栈,以进行时间戳,并将消息写入Vitess中的消息表。后端还启动了异步处理作业(处理与链接和附件的扩展预览相似的东西),最后通过他们的实时服务堆栈通过其活动的WebSocket连接将事件发送到通道中的所有连接客户端。

不幸的是,在客户中建模这些复杂的互动及其对我们系统的影响并不容易。在建造Koi Pond(我们今天的主要负载测试工具)之前,我们已经开发了多种解决方案,每个解决方案都有它的优点和缺点,其中没有以可扩展的方式测试了所有三个高级客户端操作。

这些工具之一,Puppet Show,旋转了无头铬浏览器,它跨Kubernetes群集点陷入困境,并执行一个简单的命令脚本;虽然这测试了我们的后端系统以及我们的实时服务堆栈,但这既非常昂贵,也不容易缩放。我们的实施要求每个集群都要手动旋转,我们一整天都达到150,000个模拟用户。

我们构建的另一个工具API Blast,通过URL以指定的速率调用特定的API端点(我们在此处更详细地进行了详细的API BLAST);这里的限制是我们只能一次呼叫单个端点,我们无法通过连接的客户端加载实时服务堆栈。

负载测试我们的后端服务和我们的实时服务以成本高效的方式。

增加了实际模仿的能力,我们在与规模相关的松弛的特定性能问题,包括雷鸣群,大规模信息扇出和无限的数据集。

Koi Pond是一种旋转苗条客户端的苗条客户端的工具,我们称之为KOI。 koi做了两件事:建立一个WebSocket连接并发送API调用(与我们的真实客户端有关!)。每个KOI都属于一个学校,该学校是一个控制一组高达5,000 koi的计划。学校将服务器(我们称之为KOI Keeker)定期投票。我们定义了两种工作:行为和地层,我们将在下面更详细地描述。

行为是KOI以给定频率执行的动作。行为通常包括调用单个Slack API(例如,对话.History),但如果它们彼此依赖,也可以执行多个呼叫。我们提出了一种简单的结构来定义这些行为,如下面可以在对话中看到的.history示例。

该结构有两个部分:基于API在特定生产团队中的典型使用的频率定义,以及使用API​​调用参数的序列定义,我们将在下面的示例中更详细地潜入。我们将配置文件与我们感兴趣的每个API上传一个配置文件,并且该行为缩放到我们引导的KOI的数量。

在频率部分中,配置告诉我们,在我们内部松弛工作空间中的给定分钟中,有0.2393或23.93%,用户将调用对话的可能性。我们的KOI将调用对话。以这种相同的频率。虽然有利于负载测试来查找我们系统的破坏点,但我们发现以逼真的速度调用API来模拟常规使用模式以准备客户推出。

在下面的配置中,您可以看到序列具有一些不同的组件。序列配置文件的语法位于Golang标准模板库中:

pre_actions是我们在调用API之前需要采取的步骤。在此示例中,您可以看到我们尝试将CurrentChannel设置为来自KOI的本地商店的随机通道。如果我们找不到有效的频道,我们会停止序列。

请求是序列的核心以及我们进行实际网络请求的位置。我们使用生产团队中的真实用户常用的参数定义它。

post_actions是我们在调用API之后立即采取的步骤。在此示例中,我们添加到Koi的邮件和用户ID的本地存储。

手动写出这些实现可能是乏味的,所以我们自动化它!我们构建了由我们的数据仓库支持的仪表板,允许我们在团队ID中键入,并生成我们可以易于导出的API频率列表,然后导入到工具中。这使我们能够生成密切模仿真实世界的行为的行为。

形成是一组出站网络请求(API调用或Websocket消息),百分比koi在指定的时间内执行,这意味着模拟真实的工作区的雷鸣群行为(例如,大量用户翻转到组织范围的通道,阅读最新消息,并对其进行反应)。这与在配置文件中以指定频率的所有KOI运行的行为相反。地层允许我们更现实地测试大规模用户行动对我们系统的影响。这些操作不在孤立中调用,因此这使我们在许多用户同时采取相同行动的情况下,我们的系统负载更好的举例。

例如,通过我们的API Blast工具,如果我们想测试用户翻转通告通道并查看和对消息进行响应的用户的效果,我们将仅限于以指定的速率调用反应。虽然这将测试我们的后端系统(例如,数据库和作业队列),但我们不会对我们的实时服务堆栈遇到下游影响(例如,数百万次反应的事件,这些事件会泛滥我们连接的KOI WebSockets)。

相反,请参阅下面的形成示例,我们可以测试查看消息的每个用户的逼真负载,将消息标记为读取,最终调用reamipe.add。在元数据中,您可以看到我们在六分钟内指定了它(begin_within_secs值为360),所有引导koi的10%将执行这组操作。

这就是名字“Koi Pond”来自的地方 - 我们想到了Koi在他们的池塘中如何以类似的方式与我们的模拟客户群同时采取某些行动的类似方式。

在这一月导致大客户的发布会上,我们跑去了我们惊人的QA(质量保证)团队手动测试了关键的松弛功能,同时我们启动了他们的背景活动。正如我们之前提到的那样,Slack中的某些行动非常复杂,因此挑战精确复制。我们正在努力使锦鲤池尽可能接近真正的懈怠的行为,但在此同时,手动测试有助于我们确保所有细微差别的行动都是现实地测试的。

每周,我们增加了我们模拟的KOI的数量(在客户发布之前的最后一次会议上开始5,000并最终启动500,000),并通过使我们的测试工作空间尽可能接近我们对实际的预期来改进我们的测试的保真度客户的工作区。这包括添加某些数量的私人和公共信用道,并启用我们的EKM(企业密钥管理)功能。这帮助我们识别在图形或警报中没有良好出现的错误和瓶颈,并且测试的常规节奏给了我们充分的机会来验证性能改进和错误修复。

示例:在我们的负载测试工作空间中的一个默认通道中,这是一个积极运行的KOI,我们的QA工程师手动测试文件共享。这为每个用户发送了两个WebSocket消息,完全敲击了我们的实时服务基础设施,并让我们关闭测试以防止任何生产影响。要解决此问题,我们增加了负载测试工作空间的实时服务器的展开(允许我们均匀分发更多服务器,从而减轻任何一个服务器上的负载)并为文件添加了性能优化上传代码。一旦实施了这些变化,我们将在一百万积极运行KOI的100万人再次测试了场景,并在我们的图表中几乎没有看到了昙花一现。这是我们能够在负载测试和修复之前找到的案例的一个很好的例子,并且在它对真正的客户产生影响或事件之前。

我们为团队提供了在运行API Blast(或Ad-Hoc脚本)负载测试时启动KOI的选项。这给了我们在WebSocket和实时服务器上看到负载的好处。

示例:我们的产品工程团队之一运行了API爆炸负载测试,他们在他们叫做Chat.PostMessage的速度,而我们有200,000 koi启动的速度/第二次。这使我们的实时服务器重载并帮助我们确定了一个添加速率限制以保护我们的系统的好地方。

通过背景行为,缩放koi没有任何额外的API爆炸或跑步仍然以现实的方式测试我们的系统。这是找到定期使用的瓶颈的好方法。

示例:当我们缩放到200,000 koi时,我们对我们的监控系统使用的数据库命名空间产生了重大压力。我们的监控团队能够向系统扩展系统并手动添加分片,以便我们的系统在车上大客户面前做好充分准备。

除了查找瓶颈之外,我们还能够在负载测试工作空间(我们专门为负载测试设置的生产工作空间)进行性能优化,具有大量的背景活动。其中一个示例正在将大客户迁移到Vitess - 在我们的负载测试工作空间中没有问题,我们有信心为新客户启用它。

我们还耗尽了一些筹备筹备机构,以测试许多用户立即采取的大行动。在现实生活中,想到一家公司的AMA或管理员在公告频道中发送消息。

示例:使用100万koi连接,我们有一个用户在组织宽的默认通道中发送消息(这意味着工作空间中的所有用户都在此频道中,不能离开),使用上面的示例。我们能够拥有100个用户对消息作出反应而不会引起太多麻烦,但在线程中的18次回复有关于每6秒发布的消息,我们的实时基础架构被淹没。我们了解到,我们需要在我们解决潜在问题时为这种大频道事件添加修护栏。

Koi Pond非常快速,现实地缩放 - 我们最大的测试到目前为止是单个工作空间中的200万用户,我们没有找到任何主要问题或在我们击中这个里程碑时引起任何事件。

锦鲤池塘很便宜;锦鲤池塘运行200万用户率约为傀儡展示的15万用户的0.26% - 这是客户的13倍。

Koi Pond非常安全;它连接到我们的紧急停止机制,并通过Koi Pond UI在几秒钟内关闭。我们在建立KOI POLD架构时优先考虑安全,并确保在我们的UI中清晰而直观地停止保护。此外,我们的KOI POLD基础设施是从生产中孤立的;例如,我们有一个单独的网站和vTgate(轻量级代理服务器,路由虚拟机的流量)路由我们的负载测试流量。

为我们的客户提供充分的准备,为真正顺利,诚实的反高潮发射日。这是一个很棒的新闻 - 它意味着我们所有的负载测试都有工作。

逐渐缩放是关键。在我们准备客户发射时的一点,我们直接从5000到100,000 koi。这最终导致我们的一个数据库中的应变,如果我们首先缩小到较小的数字并看到负载和冲击的逐渐增加,则可以防止这一点。

确保我们的负载测试环境尽可能逼真。由于Slack具有如此复杂和高度分布式的架构,这对我们来说是一个挑战;很难知道真实工作空间的所有不同细微差别。一个例子是我们的API Blast + KOI POLD努力之一 - 在测试我们的SSO(单点登录)流程时,我们最初使用单个SSO令牌,但以高速频率调用它。我们注意到没有超过WebSocket的事件,因此我们将测试与多个用户的SSO令牌重试,这为此操作发送了更高且准确的WebSocket事件数。虽然这并没有造成任何重大问题,但如果我们没有使用多个令牌测试,我们会错过在Websocket上的负载和我们的实时服务器。

与产品团队协调以确保该工具是易接近的,现实和安全的。我们有一些团队志愿者来测试自己的功能,我们能够收集关于对他们有挑战性并改进过程的反馈。

高保真难以实现,我们仍在努力 - 将用户传播在渠道中并实现我们所拥有的所有API是耗时的。如前所述,模拟所有细微差别并以现实的方式模拟产品中的所有细微差别并挑战。

Koi Pond使我们能够主动和现实地测试所有系统,同时具有成本效益。我们已经成功推出了大客户和大型里程碑,因为我们在准备工作中的负载测试。

展望未来,我们在锦鲤池塘建造两种主要方面。首先是不断运行锦鲤。目前,每次我们使用Koi Pond我们都启动所有客户。当其他人想要利用该工具时,这个过程是耗时的,为我们的团队增加了很多开销。我们正在努力在一直运行KOI运行的过程中,以缓解这些问题并解锁在部署和更现实的时区/区域测试中的负载测试等可能性。

我们还计划提高我们行为的保真度和灵活性。 正如我们之前提到的那样,每个KOI POND测试目前基于生产工作空间运行单个配置。 我们知道Slack使用模式根据TimeZone,Region以及它们是否使用移动或桌面而更改。 我们希望改进我们的工具以轻松反映这些用户使用模式。 向团队喊叫:Maude Lemaire,Glen D Sanford,Sara Bee,Venkat Venkatanaranappa,摩根琼斯! 想帮助松懈解决棘手的问题并加入我们的成长团队吗? 查看我们所有的开放职位并立即申请。