Page 63 - 《软件学报》2025年第7期
P. 63

2984                                                       软件学报  2025  年第  36  卷第  7  期


                 标待测系统的一些特征信息来缩小探索空间, 提高测试效率. 因此一些测试工具提供高度可扩展的测试框架, 允许
                 用户使用特定领域语言        (DSL), 根据用户自己对待测分布式系统的理解, 定义待测系统所要注入的系统故障以及
                 对应的探索策略.
                    Jepsen  [58] 作为业界广泛使用的分布式系统故障注入测试工具, 以其灵活的框架设计和全面的                       API 接口, 赋予
                 了测试人员高度自定义故障注入策略的能力, 以满足不同分布式系统测试的复杂需求. 通过编写                              Clojure 语言的代
                 码脚本及相应配置文件, 测试工程师可以详细指定欲模拟的故障类型、注入时机、持续时长及其影响范围, 从而
                 准确模拟出网络分区、节点故障、消息丢失等一系列真实世界中可能遇到的故障场景. 这种方法不仅使测试过程
                 更加灵活和定制化, 还能够针对特定的系统特性和预期的故障场景进行深入测试, 有效地揭示潜在的系统缺陷和
                 弱点. Jepsen  的高效测试能力被广泛应用于各类分布式系统, 尤其是分布式数据库的深入测试, 成功揭示了许多关
                 键的系统代码缺陷.
                    而考虑到部分系统缺陷是由多种故障组合发生事触发的, 针对多个故障的组合空间输入庞大挑战, Joshi 等
                 人  [96] 提出了  PreFail, 一个可编程的故障注入工具. PreFail 需要测试人员能够编写特定的故障组合策略, 以缓解
                 多个故障组合带来的输入空间庞大问题. 为了实现可编程性, PreFail 采用了机制和策略分离的经典原则, 将故障
                 注入框架解耦为两部分: 故障注入引擎和注入驱动程序. 故障注入引擎负责在被测系统中注入故障, 而注入驱动
                 程序则根据测试人员指定的策略决定故障注入的位置. PreFail 对引擎和驱动程序进行了抽象描述, 包括故障注
                 入点、故障执行任务以及测试环境配置等. 测试人员可以使用这些抽象在他们的策略中进行快速建模, 有效应
                 对多个故障组合的复杂测试需求.

                 3.1.4.3    反馈引导故障序列
                    虽然人工定义的模型可以有效缩小探索空间、提高测试效率, 但这种方法通常需要耗费大量人力资源, 且构
                 建的模型难以在不同系统间迁移应用. 为解决这一问题, 一些分布式系统的故障注入工具引入了自动化探索策略.
                 它们将每次测试中触发的一系列故障视为故障序列, 并自动生成这些序列作为测试输入. 这些工具在测试过程中
                 实时收集并分析系统的反馈信息, 根据反馈动态调整故障序列的生成, 以更有效地扩展测试状态空间, 从而发现更
                 多潜在问题和缺陷.
                    故障注入工具      FATE [97] 在  2011  年首次引入暴力搜索方法来探索故障序列空间. 传统暴力搜索通过系统地枚
                 举所有可能的故障组合, 逐步增加故障序列的复杂性. 为优化效率, FATE 将搜索空间分为前缀和后缀两部分: 前
                 缀是固定的操作步骤, 后缀则是故障注入点和恢复操作的组合, 从而有效减少了组合数量. 此外, FATE 引入了工
                 作流模型技术, 动态识别关键路径和节点, 优先测试关键故障序列, 最大化测试覆盖率并提升效率. FATE 在 HDFS
                 和 ZooKeeper 等分布式系统上进行了多重故障测试, 探索了超过               40 000  个故障场景, 发现了   67  个鲁棒性缺陷.
                    尽管优化后的暴力搜索在分布式系统缺陷发现上取得了一定成果, 但对于需要更长故障路径的深层缺陷, 其
                 效果有限, 因为生成长路径的故障组合序列消耗大量资源. 为提升测试效率, Gao                      等人  [79] 开发了  CrashFuzz, 一款基
                 于代码覆盖率引导的故障注入工具. CrashFuzz 通过将执行路径上的故障点按顺序排列, 并以二进制方式标记其激
                 活状态, 形成表示故障序列的二进制字符串. 初始阶段所有故障点均未激活, 生成序列<000…0>并放入种子池. 随
                 后, 通过变异种子池中的序列生成新的故障序列, 并根据代码覆盖率提升情况选择保留新种子序列. 通过这种启发
                 式搜索, CrashFuzz 不仅提升了缺陷挖掘效率和代码覆盖率, 还在 HDFS 和 ZooKeeper 等分布式系统中发现了                    4  个
                 新的鲁棒性缺陷.
                    尽管基于代码覆盖率的反馈机制提升了测试覆盖率, 但在故障注入测试中, 这种方法未必高效, 因为其核心是
                 检测分布式系统的故障处理逻辑, 而非其他业务逻辑. 仅依赖代码覆盖率可能导致大量与故障处理无关的代码被
                 探索, 降低了效率. 为解决这一问题, Mallory       [77] 测试工具在系统中插入探针, 实时捕捉关键事件信息, 如消息传递
                 和节点状态变化, 构建      happen-before 图以描述事件间的因果关系. 基于该图, Mallory 识别可能导致系统缺陷的事
                 件顺序, 并采用    Q-learning  强化学习优化故障输入序列. 成功触发新系统行为的序列获得正向奖励, 反之则获得负
                 向奖励. 通过迭代, Mallory   逐步识别最可能触发缺陷的故障序列, 提升了测试生成的质量. Chronos                  [21] 认为在分布
                 式系统中深层路径的故障处理逻辑, 通常因较少激活而更有可能隐藏缺陷. Chronos 实时计算执行路径上故障点
   58   59   60   61   62   63   64   65   66   67   68