死循环:扣不到的广告余额,记一个生产问题

前言

广告收入在各大互联网公司的营收中占据重要甚至主导地位

  • 字节跳动2020年广告收入1831亿元,占2020年实际收入的77%;
  • 百度依靠搜索承接了大部分的网络营销业务,广告营销收入占比一度达到其总营收的90%;
  • 谷歌(Alphabet) 广告收入占总营收的约80%;
  • Facebook 广告收入占总营收的约98%;
  • 腾讯 广告收入占总营收的约20%;
  • 阿里巴巴 广告收入占总营收的约60%;
  • .....

尽管各大互联网公司的具体广告平台和投放方式可能有所不同,但广告投递流程大致相似,一般包括注册登录、创建广告账户、设置支付方式、创建广告计划、设计广告创意、定义受众定向、设置出价策略、提交广告审核、广告投放、数据分析与优化等步骤。

点击查看步骤说明
  1. 注册并登录广告平台:广告投递者需要在相应的广告平台上注册并登录,如谷歌Ads、Facebook Ads Manager、腾讯广告、阿里妈妈、京东广告等。

  2. 创建广告账户:广告投递者需要创建一个广告账户,填写相关信息,如公司名称、联系方式、地址、行业等。

  3. 设置支付方式:广告投递者需要为广告账户设置支付方式,如信用卡、支付宝、微信支付等。部分平台可能要求预先充值一定金额作为预算。

  4. 创建广告计划:广告投递者需要创建一个广告计划,设置广告目标(如品牌推广、网站流量、应用下载等)、预算、投放时间等。

  5. 设计广告创意:广告投递者需要设计广告创意,包括选择广告格式(如图片、视频、轮播图等)、编写广告文案、添加呼叫操作按钮等。

  6. 定义受众定向:广告投递者需要根据目标客户群体设置受众定向,如地域、年龄、性别、兴趣、行为等。

  7. 设置出价策略:广告投递者需要为广告设置出价策略,如CPC(每次点击成本)、CPM(每千次展示成本)、CPA(每次行动成本)等。

  8. 提交广告审核:完成广告设置后,广告投递者需要提交广告创意进行审核。广告平台会根据其广告政策对广告进行审核,确保广告内容合规。

  9. 广告投放:广告审核通过后,广告将按照投递者设置的计划、受众定向、出价策略等进行投放。广告投递者可以在广告平台上实时查看广告投放效果。

  10. 数据分析与优化:广告投递者需要定期分析广告数据,如曝光量、点击量、转化率等,根据分析结果对广告计划、创意、定向等进行优化,提高广告效果。

问题现象

月初对账,部分客户账单异常,扣费额超出余额,超限投递了广告。

背景:广告扣费流程

假设您是一位广告投递者,在某平台投放广告后,服务商的扣费流程一般可以简化为如下:

sequenceDiagram participant 广告投递者 as 广告投递者 participant 广告服务商 as 广告服务商 广告投递者->>广告服务商: 设置预算(100元) 广告投递者->>广告服务商: 设置单次曝光扣费(0.011元) 广告服务商->>广告投递者: 确认设置 loop 检查预算是否充足 广告服务商->>广告服务商: 预算充足? Note right of 广告服务商: 是 广告服务商->>广告服务商: 进行一次广告曝光 广告服务商->>广告服务商: 扣除单次曝光费用 广告服务商->>广告服务商: 更新剩余预算 Note right of 广告服务商: 否 rect PapayaWhip 广告服务商->>广告投递者: 预算不足单次抵扣,广告投放结束 end end

为了让客户有更好的体验,一般最后只要账户还有余额,就进行一次抵扣,直到账户的余额扣完,让利给客户。所以上面标红的部分变成了:

sequenceDiagram participant 广告投递者 as 广告投递者 participant 广告服务商 as 广告服务商 Note over 广告投递者,广告服务商: .... loop 检查预算是否充足 Note right of 广告服务商: 是 广告服务商->>广告服务商: ... alt 预算不足单次曝光费用,但仍有余额 广告服务商->>广告服务商: 进行一次广告曝光 广告服务商->>广告服务商: 扣除剩余余额 广告服务商->>广告服务商: 更新剩余预算(0元) 广告服务商->>广告投递者: 预算已用完,广告投放结束 end Note over 广告投递者,广告服务商: .... end

实际流程

因为每次曝光的费用都是在广告投递的时候配置好的,所以扣费时的 payamt 支付金额是从配置中获取。这个时候如果想要将余额抵扣完,一般需要进行两次抵扣,第二次抵扣的金额依赖于第一次抵扣时候抵扣接口返回的账户余额,然后使用剩下的金额金额抵扣(标黄部分)。

sequenceDiagram participant ad as 广告中台 participant mid as 扣费中台 participant acct as 账户托管系统 participant dev as 终端(web/ios/android..) Note over ad, acct: 广告曝光 loop rect Snow ad->> mid: 确认客户信息,查询余额 mid->>acct: 查询余额 acct ->> mid:返回余额 mid ->> ad:返回余额 end alt 余额 不为 0 rect Snow ad->> dev: 曝光 rect PapayaWhip ad->>mid: 扣费(配置曝光额度) mid ->> acct:扣费 acct ->> mid:扣费结果 alt 扣费成功 mid ->> ad:扣费结果 else 扣费失败 rect yellow mid ->> acct:扣费(账户剩余金额) acct ->> mid:扣费结果 mid ->> ad:扣费结果 end end end end else 余额为 0 rect PapayaWhip ad -->> ad :剔除出曝光列表 Note right of ad: 不再曝光 <br> 直到下次进入曝光计划 end end end

问题原因

直接原因

在某些场景下,客户数据托管系统余额不足时没有返回剩余金额,上游系统直接使用了余额转int的函数,将余额信息初始化成了 0,导致二次抵扣的系统认为客户已经没有余额,所以没有进行二次抵扣。但是客户数据查询接口能正常查到账户余额,所以广告又一直在曝光。

根因

  • 某个中间系统年前进行了重构,代码有 bug(将获取不到的余额信息初始化成了 0),导致在用户信用额度未使用的情况下,抵扣接口返回了剩余金额 0 的信息
  • 测试同学场景考虑不充分,仅仅考虑了一种余额不足的场景,没有考虑其他余额不足场景

余额不足场景验证场景较为单一(初始化余额,支付大金额),测试同学验证的场景,刚好命中代码特殊逻辑分支,返回了余额。

出现上面的现象之后,内部进行了排查,定位流程非常复杂:

  • 系统间调用链路很复杂
  • 所有系统都没有业务告警或者系统异常,意味着所有的逻辑都正常处理了,有定位经验的大家应该都知道这样的问题最难定位。
  • 执行二次抵扣的系统长时间没有版本导致几乎无人知道这个逻辑
  • 那个月发布的版本很多,无法确定是什么版本引入的
  • ....
    那么有没有什么手段能提前发现这些问题呢?

重构版本常见验证方法

并行测试

并行测试 :在重构前后的系统上同时运行相同的测试用例,并对比测试结果。这种方法可以确保在相同条件下对两个系统进行对比,从而发现潜在的问题和差异。

优势
  • 可以在相同条件下对两个系统进行对比,提高测试的准确性。
  • 可以快速发现潜在的问题和差异。
限制
  • 需要额外的资源和时间来同时运行和维护两个系统。
  • 可能无法完全模拟真实用户的行为和场景。
  • 存在自动化用例的改造工作量:
    • 需要对全量返回字段进行全量比对改造
    • 需要对全量持久化存储的字段进行了全量比对改造
    • 少数的不能完全一致的数据,需要逐个确认,或者验证其满足一定规则,不够精确,时间耗费较多

PS:自动化用例在编写之初就一定要设计好,才能在后续方便改造。

现网引流

方法一可以帮助简化对测试结果的验证,但是测试输入还是人工构造,与实际调用可能存在差异 且 不够丰富,漏掉一个场景就有可能放过一个bug。所以直接使用线上的请求测试在辅助验证方面是一个高效的方法。

但是这种测试方法有一定的局限性。简单来说,这种方式适合测试读接口,不太适合或者说是难以测试写接口。

优势
  • 请求场景丰富、高效
  • 可以快速发现潜在的问题和差异。
限制
  • 需要进行请求聚合,不然测试环境无法支撑请求量
  • 直接使用线上的存储时,只适合测试读接口,不太适合或者说是难以测试写ni接口
  • 测试环境拷贝线上数据时:
    • 安全风险
    • 流量发生与用户数据拷贝无法同时完成,所以引流主要是验证变化,而不是与现网进行对比

其他验证手段

以下是服务转运维之后,在线上可以做的一些质量保证的方法:

测试方法 方法介绍
A/B测试 将用户流量分为两部分,一部分访问现有系统(A),另一部分访问重构后的系统(B)。通过比较两个环境下的用户行为、性能指标和转化率等数据,评估重构前后系统的差异。
蓝绿部署 在两个不同的环境(蓝环境和绿环境)上部署重构前后的系统。通过将流量切换到不同的环境,可以实时观察和比较两个系统的性能和功能表现。
影子部署 在重构后的系统上部署一个影子服务,该服务接收与现有系统相同的请求,并在后台运行。通过比较两个系统的响应和性能数据,可以评估重构前后的差异,而不影响用户体验。
混沌测试 在重构前后的系统上同时引入故障或异常情况,以评估系统在不同环境下的稳定性和容错能力。混沌测试有助于发现潜在的问题,并确保系统在各种故障情况下的处理逻辑保持一致。
线上验证的优势和限制
测试方法 优势 限制
A/B测试 - 可以直接观察真实用户在两个系统中的行为和反馈。
- 可以实时调整流量分配,根据测试结果优化系统。
- 可能需要较长的时间才能获得足够的数据来支持决策。
- 需要确保用户在A/B测试过程中的隐私和数据安全。
蓝绿部署 - 可以实现平滑的系统升级和回滚,降低风险。
- 可以实时观察和比较两个系统的性能和功能表现。
- 需要额外的资源和成本来维护两个不同的环境。
- 可能需要复杂的流量切换和监控机制。
影子部署 - 可以在不影响用户体验的情况下评估重构前后的差异。
- 可以实时收集和分析两个系统的响应和性能数据。
- 可能需要额外的资源和成本来部署和维护影子服务。
- 由于影子服务在后台运行,可能无法直接观察用户的反馈。
混沌测试 - 可以评估系统在各种故障情况下的稳定性和容错能力。
- 可以发现潜在的问题,提高系统的可靠性。
- 可能需要专门的工具和技能来设计和执行混沌测试。
- 混沌测试可能引入不稳定性,需要在安全的环境下进行。

在实际应用中选择适合的方法时,需要根据项目需求、资源和风险承受能力等因素进行权衡。

总结

信息在多个系统间传递的时候,很有可能会失真,每一个生产事故的背后,都是宝贵的经验和教训,都是项目成员的血泪史,保持敬畏。

在进行对比测试时,务必确保测试用例完整、测试数据一致,并关注测试过程中的问题和反馈,进而评估重构前后系统的性能、功能和稳定性,以确保处理逻辑的一致性。

同时对比测试也有助于发现潜在的问题,从而提高系统的质量和可靠性,有条件的可以根据实际情况结合使用多种方法,应用到日常版本中去。

posted @ 2023-08-10 10:46  Bingo-he  阅读(3756)  评论(3编辑  收藏  举报