大数据/质量测试的实用DevOps
数据密集型应用程序的质量测试 (QT) 旨在验证 DIA 原型是否能够提供最终用户期望的扩展性、效率和稳健性水平。Apache Storm、Spark、Hadoop、Cassandra 和 MongoDB 等常见的大数据技术彼此之间相当不同,因此必须认识到 QT 需要使用多种工具来测试复杂的 DIA。
例如,Cassandra 和 MongoDB 数据库最近得到了 Apache JMeter 的支持,Apache JMeter 是开源领域最先进的负载生成工具。MongoDB 受到原生支持,而 Cassandra 则通过外部插件支持。Apache Hadoop 和 HBase 也得到了部分支持,现在可以在 JMeter 中使用。这意味着与这些技术的负载注入相关的研究挑战是有限的,因为 JMeter 作为压力测试的主要开源解决方案已经存在。基于以上,我们在本章中主要讨论流式 DIA 范围内的 QT,这在开源社区中受到的关注有限。
设计质量测试工具面临着一些挑战[1]。在这方面,对于 DIA 还没有正式的方法论,我们认为一些关键挑战可以概括如下。
- 负载注入执行器设计。在传统的负载注入中,工作负载提交依赖于客户端-服务器模型,其中外部工作线程将作业提交到应用程序。然而,这种模型对于 Storm 等平台并不自然,在 Storm 等平台中,消息注入由专门的软件组件(称为 spout)完成,这些组件是应用程序本身的一部分,并且注入打包为消息的特定工作单元,这些消息流经系统。在这种系统中,负载注入执行器不应作为外部元素实现,而应作为应用程序的内部元素实现。因此,开发用于数据库的 QT 工具与开发用于流式平台的类似工具之间存在概念上的差异。例如,作为应用程序本身的内部组件,工作负载生成器在流式应用程序中的资源使用情况将累积到应用程序本身的资源消耗。这对于数据库系统可能不可接受,但对于流式应用程序来说是必需的,在流式应用程序中,消息的注入会消耗一个单独的资源池。虽然也可以考虑外部实现,例如通过提供与 Twitter 用于将数据推送到外部方所用的服务等效的服务,但内部实现的一个显着优势是,负载注入执行器可以直接访问 DIA 内使用的數據结构,包括开发人员定义的自定义消息结构。这使得最终用户可以使用 DIA 本身开发的相同 Java 类来更轻松地定义发送到系统的流式工作负载,并自动执行实验。但是,这种方法的一个重要含义是,负载注入需要提供为一个嵌入式库,该库可以链接到应用程序代码中,开发人员通过 IDE 定义测试工作负载。
- 可扩展性测试。任何负载注入工具的要求都是能够测试系统扩展的能力,即在工作负载并行级别提高时(例如,更多用户、更高的数据速度、更大的数据量等)提供性能和可扩展性方面的服务质量 (QoS)。因此,预计对 QT 工具的良好实现将能够根据最终用户的要求生成额外的负载,直到观察到一个或多个资源的饱和。QT 可以做到这一点。
- 流式工作负载生成。基于流式的 DIA 通常侧重于分析传入消息以查找特定主题,并在满足消息有效负载上的预定义条件时触发某些操作。因此,一个研究挑战是提供足够的工具支持,让用户可以轻松地生成时变工作负载和时变消息内容。理想情况下,这些工作负载应该尽可能接近开发人员公司在生产环境中看到真实的工 作负载。例如,在 Twitter 流式数据的情况下,人们希望生成类似于普通 Twitter 提要的工作负载,但这些工作负载在单个消息类型的到达速率方面是可控的(例如,原始推文的到达速率与转发推文的到达速率,或者来自特定用户的到达速率),以及触发 DIA 特定操作的消息出现的频率。我们在整个 QT 研究活动部分系统地研究了这个问题,并且开发了一种专门的数学理论来解决这个问题。
有各种各样的负载测试工具可用于分布式系统,包括商业工具(例如,IBM Rational、HP LoadRunner、Quali、Parasoft 等)和开源工具(例如,Grinder、JMeter、Selenium 等)。但是,所有这些工具主要都是为传统的 Web 应用程序开发的,在传统的 Web 应用程序中,传入的负载是 Web 流量,用户与应用程序前端(网站)交互。在 DIA 的情况下,传入数据(例如数据库、流)是主要的工作负载驱动因素。虽然数据库测试相当普遍,但用于将数据流注入 DIA 的开源解决方案却很缺乏。在介绍 DICE 解决方案来解决这个问题之前,我们将更详细地讨论现有的负载测试工具。
- Grinder。这是一个用于对 Java 应用程序进行分布式测试的框架。除了测试 HTTP 端口外,它还可以测试 Web 服务(SOAP/REST),以及通过 JMS、JDBC、SMTP、FTP 和 RMI 等协议公开的服务。该工具执行用 Java、Jython 或 Clojure 编写的测试脚本。测试可以是动态的,这意味着脚本可以根据上一个操作的结果来决定要执行的下一个操作。该工具已经成熟,首次发布是在 2003 年。它非常流行,每周下载量约为 400 次。Grinder 的一个局限性是缺乏组织良好的志愿者社区来支持该工具。
- Apache JMeter。这是一个分布式负载测试工具,在负载注入功能方面提供了与 Grinder 类似的功能。如果与 Markov4JMeter 结合使用,该工具还可以具有概率行为。有趣的是,该工具还具有对 MongoDB(一个 NoSQL 数据库)的原生支持。该工具在可扩展性方面表现出色,这是通过插件实现的。JMeter 的一个局限性是,在 Javascript/AJAX 在性能方面起主要作用的网站上,Web 导航可能不具有代表性,因为 JMeter 不具备像复杂浏览器那样的 Javascript 功能范围。JMeter 得到了庞大的 Apache 基金会社区的支持。
- Selenium。这是一个流行的库,它可以自动控制 Web 浏览器,例如 Internet Explorer 或 Firefox。它允许使用本机 Java API 执行测试。此外,可以通过向浏览器添加 Selenium 插件并手动执行操作来记录测试脚本。一个扩展(以前称为 SeleniumGrid,现在已集成到主 Selenium 工具的稳定分支中)允许执行分布式负载测试。
- Chaos Monkey。这是一项在 Amazon Web Services 上运行的开源服务。该工具用于在自动扩展组中创建故障,并帮助识别云应用程序中的故障。设计灵活,可以扩展到与其他云提供商合作并提供其他功能。该服务有一个完全可配置的时间表,用于执行操作的时间,默认情况下,该服务在非假日工作日上午 9 点到下午 3 点之间运行。在 .NET 中为 Microsoft Azure 开发了一个类似的工具,称为 WazMonkey,它提供了与 Chaos Monkey 类似的功能,例如在给定的 Azure 部署中随机重新启动或重新映像角色实例。
DICE QT 工具是两个独立模块的组合
- QT-LIB:一个用于在基于 Storm 和基于 Kafka 的应用程序中定义负载注入实验的 Java 库。
- QT-GEN:一个用于生成工作负载跟踪的工具,这些跟踪可以使用 QT-LIB 注入到系统中。
QT-LIB 以 jar 文件的形式提供,可以打包在任何基于 Java 的 Storm 拓扑中,提供用于负载注入和工作负载调节的自定义 spout。该工具可以通过 MongoDB 获取要推送到 DIA 的外部数据(对于可以作为 JSON 文件导出的大型数据集),也可以通过外部文本文件获取。JSON 文件使用与 MongoDB 兼容的语法。下面,我们将更详细地介绍各个模块。
QT-LIB 模块提供了一组自定义的 spout,用于自动化在 DIA 中注入工作负载。这些 spout 的工作原理很简单:一旦 DIA 部署,这些 spout 就会根据用户指定的工作负载自动生成元组。负载生成接口可供最终用户指定输入数据源(例如,CSV、MongoDB);该接口为 spout 提供输入元组以将负载注入系统,并且可以轻松地适应其他数据库或其他文本或二进制输入源。即使 QT-LIB 成为被测拓扑的一部分(作为代码和逻辑架构),被测系统也是处理数据的 Bolts 集合。因此,Bolts 及其之间的关系嵌入在 DIA 代码中。
QT-GEN
[edit | edit source]我们讨论 QT 最先进的功能,即从给定的 Storm 消息跟踪中自动生成人工工作负载的能力。其想法是在给定的工作负载跟踪中区分一组消息类型,并生成一个新的跟踪,该跟踪具有与初始跟踪类似的特征,但与初始跟踪不同,并且具有任意用户指定的到达率。QT 假设有一个 JSON 文件可用,其中每个条目代表要序列化为元组的消息。
QT-GEN 工具接受输入一个 JSON 文件,该文件包含任意长的此类消息序列,对其进行解析以提取问题时间戳序列,然后生成一个新的消息序列,其中消息以交替方式排列,以保留与原始跟踪中定义的用户类型之间类似的相关性,然后生成一个新的消息序列,其中消息以交替方式排列,以保留与原始跟踪中定义的用户类型之间类似的相关性,如原始跟踪中所见。作为一个简单的例子,对于 Twitter 跟踪,QT 工具可以生成一个新的跟踪,其中包含
- 与原始跟踪中相同的推文和转发比例,后者由 Twitter JSON 数据结构中的特定字段标识。
- 推文和转发之间统计上类似的时间间隔,以便推文和转发的数量以及其峰值的频率和相关性也在人工工作负载中得到复制。
QT 工具可以使用称为标记马尔可夫到达过程的一类流量模型对这种相关性进行统计分析并尽可能地在人工工作负载中复制它,标记马尔可夫到达过程是隐马尔可夫模型的一种特殊类别。马尔可夫到达过程(MAP)是一类随机过程,用于对来自流量流的到达进行建模。标记 MAP(MMAP)是 MAP 的扩展,允许对多种类型的流量到达进行建模。QT-GEN 库为 QT 工具提供了后端,旨在使用 MMAP 拟合标记跟踪,并随后生成代表性跟踪。由于标记跟踪的统计描述符与 MMAP 的参数之间通常存在复杂的非线性关系,因此后一个问题非同小可。
QT 方法
[edit | edit source]下图说明了针对参考 Storm 基应用的质量测试总体方法。
主要方法步骤如下
- 将应用程序(即拓扑)提交到云测试平台
- 使用代表性工作负载进行测试,并收集初始日志(例如,JSON 格式)
- 将日志提交到 QT-GEN 工作负载生成器
- 生成新的工作负载,以使用自定义 QT-LIB spout 注入系统
- 提交启用 QT 的拓扑,并使用 QT-LIB spout
- 执行自动测试
- 在监控平台(D-MON)或交付服务(Jenkins 仪表板)上可视化结果
开放挑战
[edit | edit source]本章概述的解决方案负责在流处理系统中注入负载,目的是自动暴露性能和可靠性异常。虽然可以对标记数据进行建模,但目前流处理系统中使用的负载测试解决方案无法以编程方式指定消息有效载荷的数据内容。显然,流处理系统的响应也将取决于数据本身的内容,因此可以预见,可以定义更高级的工具来扩展所提出的方法,以涵盖内容、数据概念等。
本章没有探讨的另一个方面是质量测试工具链的可扩展性,这与设计为在数十或数百个节点上运行的数据密集型应用程序相关。这种配置要求质量测试过程本身是分布式的,以避免输入流生成中的瓶颈。有针对云负载测试的商业解决方案,但它们在 Big data 技术环境中的使用仍处于起步阶段。
应用领域:已知用途
[edit | edit source]生成用于负载测试的人工 Twitter 跟踪
[edit | edit source]让我们考虑一个从 Twitter 流中获取数据的流处理系统。当然,为了测试系统,我们需要一些 Twitter 数据。不幸的是,Twitter 和其他社交媒体平台需要付费才能获取和使用其数据集。虽然我们可以购买一些或回放一些玩具数据集,但最好有一个免费的工具来生成类似于真实数据集的人工数据集。QT 提供了这种功能。
起点是考虑来自 Twitter 或类似平台的消息的 JSON 模板。例如,这可能类似于此 JSON 文件
{ "className" : "gr.iti.mklab.framework.abstractions.socialmedia.items.TwitterItem",
"reference" : "Twitter#00000000000000000",
"source" : "Twitter" ,
"title" : "@YYY: 4 DAYS TO GO #WorldCups",
"tags" : [ "WorldCups"],
"uid" : "Twitter#000000000",
"mentions" : [ "Twitter#111111111" , "Twitter#22222222222"],
"referencedUserId" : "Twitter#138372303",
"pageUrl" : "https://twitter.com/CinemaMag/statuses/123456789123456789",
"links" : [ "http://fifa.to/xyxyxyxy"],
"publicationTime" : 1401310121000,
"insertionTime" : 0,
"mediaIds" : [ "Twitter#123456789123456789"],
"language" : "en",
"original" : false,
"likes" : 0,
"shares" : 0,
"comments" : 0,
"_id" : "Twitter#123456789123456789"}
特别要注意 JSON 文件包含一个时间戳字段,此处为“publicationTime”,以及几个可用于对推文类型进行分类的字段,例如“original”,它将推文分成两类:推文和转发。
在基于 Twitter 的真实 DIA 中,此类消息在发布后立即收到。我们的目标是从给定的 Twitter 跟踪中生成一个新的 JSON 跟踪,并具有以下属性
- Twitter 跟踪中的推文到达率与新跟踪中的推文到达率相同
- 人工跟踪和原始跟踪具有类似的推文突发生成概率
QT-GEN 工具确保了这两个属性。给定跟踪、时间戳字段(例如,“publicationTime”)和分类字段(例如,“original”),它输出一个类似于原始 Twitter 跟踪的新 JSON 跟踪,但并不完全相同。
负载测试 Kafka 管道
[edit | edit source]我们现在将说明 QT-LIB 在 Kafka 中的实际应用。下面我们展示了一个紧凑的 示例,该示例包含在 QT-LIB 发行版中。最初,与 Storm 一样,我们构造一个 QTLoadInjector 工厂,该工厂将组装负载注入器。此外,我们指定输入跟踪文件的名称,该文件假定已打包在数据密集型应用程序的 jar 文件中。
package com.github.diceproject.qt.examples;
import com.github.diceproject.qt.QTLoadInjector;
import com.github.diceproject.qt.producer.RateProducer;
public class KafkaRateProducer {
public static void main(String[] args) {
QTLoadInjector QT = new QTLoadInjector();
String input_file = "test.json"; // this is assumed to be a resource of the project jar file
我们现在准备为 Kafka 实例化一个 QT 负载注入器,称为 RateProducer
RateProducer RP;
RP=QT.getRateProducer();
String topic = "dice3"; // topic get created automatically
String bootstrap_server = "localhost:9092";
这里我们假设我们的目标主题称为 *dice3*,并且它由本地计算机上的端口 *9092* 上的 Kafka 实例公开。这对应于所谓的 Kafka 引导服务器的端口,不应与与 Kafka 关联的 Zookeeper 实例的端口混淆。我们现在可以使用 run() 方法立即启动负载测试实验。
RP.setMessageCount(101);
RP.run(bootstrap_server, topic, input_file);
这些将读取类似于 QT-GEN 创建的 JSON 消息,这些消息来自之前声明的 *test.json* 文件。该文件必须与应用程序 JAR 一起发布,以便 QT-GEN 可以将其打开为本地资源。生成的示例生成了 101 条消息来说明 QT-LIB 在跟踪运行时超过时的行为,因为在这种情况下,跟踪由 100 条消息组成。QT-LIB 将从头开始循环重启跟踪,将第一条 JSON 消息重新发送为第 101 条消息。
结论
[edit | edit source]DICE QT 的主要成就如下
- DICE QT 允许在基于 Storm 的应用程序中注入负载,使用自定义 spout,这些 spout 可以重现消息的表格到达率,或者以受控方式将存储在文本文件或外部数据库(即 MongoDB)中的消息注入。
- DICE QT 可以分析由不同类型消息组成的负载跟踪,并将这些消息的观察到的到达间隔时间拟合到称为 MMAP 的隐马尔可夫模型的特殊类别中,从中可以生成新的统计上类似的跟踪来评估不同负载情况下的系统。
- DICE QT 还可以将负载注入 Kafka 主题,因此支持各种各样的目标,包括 Spark 应用程序。
参考文献
[edit | edit source]- ↑ André B. Bondi (2015). 软件和系统性能工程基础:流程、性能建模、需求、测试、可扩展性和实践. Addison-Wesley.