前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用流量保障搜索质量的实践

利用流量保障搜索质量的实践

作者头像
政采云前端团队
发布2023-09-01 19:56:15
1960
发布2023-09-01 19:56:15
举报
文章被收录于专栏:采云轩

一 背景

政采云的搜索服务是基于 Elasticsearch 的在线分布式搜索,为内部业务提供结构化和非结构化数据的多条件检索,支撑政采云PC端、APP端、小程序端的搜索能力。

搜索以中间件形式提供服务,由于无法感知外部业务在哪用、怎么用,导致搜索测试一直沿用人工梳理场景,接口测试覆盖场景的方式。可通过人工去做,一是效率不高,二是场景覆盖不全。所以搜索的质量工作一直被如下问题所困扰:

  1. 搜索对外提供了 171 个检索条件,不同条件的组合,会流转到不同代码分支。一旦改动公共层代码,不确定回归场景是否全面?
  2. 若回归场景覆盖不全,如何自动识别未覆盖的场景?
  3. 识别到未覆盖场景,如何自动转化成场景用例?
  4. 转成场景用例,如何快速实现自动化?

基于上述问题,实践了一套基于流量的质量保障方案。

二 搜索质量保障方案

2.1 整体保障方案

目标:借助流量区分活跃和非活跃代码,针对活跃代码,使用场景计算,自动识别和构建场景用例。针对非活跃代码,通过人工覆盖,补齐场景用例。

接下来分别介绍:活跃代码保障策略,非活跃代码保障策略,自动回归策略。

2.2 活跃代码保障

2.2.1 保障策略

核心思想:借鉴流量录制回放的思路,通过采集 Dubbo 调用日志,清洗出场景数据,针对场景数据进行计算,生成场景用例。策略包含 3 个节点:

  1. 日志采集节点

外部应用通过 Dubbo 调用搜索,搜索会输出一条日志,日志内容包含入参等信息。

  1. 数据清洗节点

此节点会根据指定格式清洗 Dubbo 日志,生成场景数据。

  1. 场景计算节点

此节点是整个策略中最核心的节点,主要包含 3 块功能:1)入参模板化;2)生成模板指纹;3)根据指纹对流量去重。接下来详解实现方式。

2.2.2 场景计算

入参模板化

外部应用传给搜索的入参是一个 JSON(图1到图2),搜索会把 JSON 转化成 ES 的查询语句(图2到图3),只要捕获业务传入多少种入参(图2),就能统计出有多少种搜索场景。

入参模板化方式有2种 :

  1. 按字段方式生成模板
代码语言:javascript
复制
// 仅供说明,非真实业务字段

搜索条件:
{
 "bussinessScope": "浙江",
 "status": true,
 "keywords": "打印机"
}

生成的模板:
{
 "bussinessScope": "@",
 "status": @,
 "keywords": "@"
}

上述示例对 bussinessScope、status、keywords 三个字段进行限定查询,类似 MySQL 的 where bussinessScope='浙江' and status=true and keywords='打印机'。只要查询字段相同,无论值怎么变,对搜索来说都是一类查询。按字段方式生成模板,只需替换掉 value,保留 JSON 骨架即可。

  1. 按字段和值的方式生成模板
代码语言:javascript
复制
// 仅供说明,非真实业务字段

如上图所示:查询已上架的黑色数据线,搜索条件:
{
 "attribute": "颜色:黑色", 
 "status": true, 
 "keywords": "数据线" 
}

生成的模板:
{
 "attribute": "颜色:黑色",
 "status": @,
 "keywords": "@"
}

上述示例对 attribute、status、keywords 字段进行限定查询,还需根据 attribute 的值进行数据匹配。针对有业务含义的搜索条件,需要保留对应的 value 值。生成具有业务含义的 JSON 骨架。

生成模板指纹

模板生成后,会根据模板算 MD5,生成唯一指纹。为什么要生成唯一指纹?因为搜索日均调用百万+,里面包含了大量重复查询。为了快速识别出重复查询,本方案会对每一个模板生成指纹,只要指纹相同,就属于一类查询。

代码语言:javascript
复制
// 仅供说明,非真实业务字段

描述:查询已上架的打印机
搜索条件:
{
 "status": true,
 "keywords": "打印机"
}

生成的模板:
{
 "status": @, 
 "keywords": "@" 
}

模板指纹:D8AD32393C65D62C8658A9D699A8C190
去重

采集到新流量,生成新指纹,新指纹与已有指纹进行匹配,若相同则跳过。通过指纹匹配,相同指纹的搜索会被归为一类(如下图示例)。这样既能快速发现新场景,又能识别出重复流量。

代码语言:javascript
复制
// 仅供说明,非真实业务字段

描述:查询已上架的打印机
搜索条件1:
{
 "status": true,
 "keywords": "打印机"
}

生成的模板1:
{
 "status": @, 
 "keywords": "@" 
}

模板指纹1:D8AD32393C65D62C8658A9D699A8C190

////////////////////////////////////////////

描述:查询已上架的三星手机
搜索条件2:
{
 "status": true, 
 "keywords": "三星手机" 
}

生成的模板2:
{
 "status": @, 
 "keywords": "@" 
}

模板指纹2:D8AD32393C65D62C8658A9D699A8C190

模板1和模板2生成的指纹是一致的,通过对每一个模板的指纹进行对比,就能识别出相同搜索条件。
流量计算产出的结果

基于搜索现有流量,通过场景计算,自动生成线上P1场景用例 618 条,P2场景用例 516 条,P3场景用例 58 条,P4场景用例 161 条,总计 1353 条

2.3 非活跃代码保障

2.3.1 保障策略

流量覆盖不到的代码是非活跃代码,保障策略采用人工覆盖。搜索的非活跃代码主要有:1)开关;2)异常场景;3)未使用的方法。分别通过如下方式保障:

  1. 开关,打开和关闭开关,人工调用接口,形成用例。
  2. 异常场景,通过阅读代码,人工构造参数,形成用例。

2.4 自动回归

通过流量和人工方式构建了场景用例,就得让用例产生价值。产生价值的方式是让用例自动“活”起来。搜索自动回归的流程如下,重点在:「预期结果池」和「校验规则」的建设。

2.4.1 预期结果池

目的:同一查询条件,一定命中相同预期结果

优化前:固定关键字即时搜索。

优化后:测试用例首次执行的结果,自动复制到预期结果池,非首次执行将查询预期结果池。

  1. 为什么要建立预期结果池?

原因1:线上同一个搜索条件,间隔一段时间后再次搜索,存在返回结果不相同的情况。造成该情况的原因:用户操作或定时任务导致状态变更。如:A条件,第一次搜索返回 3 个商品 A、B、C,一段时间后,商品 B 下架。相同条件二次搜索返回 A、C、D。动态的预期结果不能很好的做校验,为了消除变动带来的影响,所以建立预期结果池。

原因2:线上索引数据 1亿+,若每条用例执行都扫 1亿+的数据,易产生慢SQL。预期结果池是独立索引,数据量几十万,相比查线上索引,速度快且不易产生慢SQL。

  1. 预期结果池里数据的新增和失效

新增数据:用例库新增一条场景用例,首次执行会查询线上索引,同时把搜索结果复制到预期结果池。当用例第二次查询,自动路由到预期结果池。失效数据:逻辑变更测试通过,删除原有数据,重新走新增数据流程。

2.4.2 校验规则

目的:根据使用场景,建立不同的校验规则。 优化前:自动化脚本里硬编码校验点。优化后:脚本与用例、校验规则解耦,根据使用场景,建立不同的校验规则。

当前自动化落地在2个场景:接口测试、重构测试,分别建立了2套校验规则。

  1. 接口测试规则

校验重点:准确性。分为:总数准确和字段准确。总数准确:结合预期结果池,对比预期总数与实际总数。用例库新增一条场景用例,首次执行会查询线上索引,记录搜索结果总数(预期结果),同时把搜索结果复制到预期结果池。当用例第二次执行,自动路由到预期结果池。若二次搜索结果总数不一致,说明代码逻辑存在问题。字段准确:按字段维度进行校验。比如:校验区域字段,校验内容:「区域=浙江」。会校验每一个返回结果的区域字段是否等于浙江,或者包含浙江。

  1. 重构测试规则

校验重点:全量对比返回结果和结果顺序。即同一搜索条件,新老接口返回值和返回顺序必须强一致。结果:沉淀2套场景校验规则,总计 37 个。其中接口测试规则 36 个(8个P1场景规则,19个P2场景规则,8个P3场景规则,1个P4场景规则),重构测试规则1个。

三 保障方案在项目中的落地

23年搜索代码将整体重构,要求测试人员对全场景进行保障。上半年分别进行了2次重构工作,内容如下:

  • 改动点
    • 以业务Id 作为分表键,数据分表存储。
    • 4个P2服务重构。
  • 风险点
    • 路由逻辑。路由出错,将导致搜索结果为空。
    • 业务逻辑。场景覆盖不全,将导致搜索结果不准确。
  • 质量保障的挑战
    • 全场景覆盖,人工回归成本高。
    • 服务重构前后,同一搜索条件,返回结果和结果顺序必须强一致,采用人工对比既痛苦又容易漏测。
  • 保障方案
    • 场景覆盖:采集 Dubbo 调用日志,清洗出场景数据,针对场景数据进行场景计算,最终生成场景用例。
    • 用例执行:自动执行用例,自动校验返回结果。
  • 结果
    • 预发环境,自动构建基础服务测试用例 4128 条,协议服务测试用例 6322 条,全量服务测试用例 4174条。
    • 自动化发现Bug:7例。剖析其中 1 例Bug,阐述人工测试,会产生的漏测点。

该Bug发现于搜索重构项目,使用重构校验规则(全量对比返回结果,以及结果顺序)。

Bug描述:搜索结果顺序不一致,导致对比失败

Bug根因:老索引的id字段是 long 类型(左图),新索引的id字段是 keyword 类型(右图),字段类型变更,引发字段排序变化

易漏测点:在海量数据对比时,容易忽视顺序变化引发的问题,继而发生漏测。因为新老接口都返回相同数据,仅商品位置发生了变化。业务影响:上游业务搜索出商品,并按商品id排序,然后放到定时任务里执行。当商品位置变化,会造成已执行过的商品被重复执行,导致任务报错。

四 未来规划

  • 线下环境使用流量录制回放系统。
  • 探索录制回放(mock形式)与本方案(真实调用)的相互结合。
  • 探索基于代码覆盖率的场景覆盖。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 政采云技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 二 搜索质量保障方案
    • 2.1 整体保障方案
      • 2.2 活跃代码保障
        • 2.2.1 保障策略
        • 2.2.2 场景计算
      • 2.3 非活跃代码保障
        • 2.3.1 保障策略
      • 2.4 自动回归
        • 2.4.1 预期结果池
        • 2.4.2 校验规则
    • 三 保障方案在项目中的落地
    • 四 未来规划
    相关产品与服务
    云数据库 MySQL
    腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档