当业务增长越来越快,随之而来的研发规模急剧扩大、迭代上线和变更愈发频繁给线上业务带来了不小的冲击,初创公司如何应对这一难题?本文将基于店匠的实践经验,详细分析如何用最小成本发现并修复,频繁迭代上线影响线上业务稳定性和关键指标的问题。
一、问题场景
店匠科技成立于 2017 年,为全球 Shopping Cart SaaS 提供品牌出海主题、订单管理、营销插件、多语言店铺、数字营销营销、多货币和安全结算、数据 dashboard、邮件和会员管理等功能的企业级解决方案。同时,店匠科技持续打造平台商业生态,通过 APP 的形式整合了 ERP、支付、物流仓储、选品供应链、营销、推广渠道和用户运营等跨境电商产业链条每个环节的优质企业提供的服务和解决方案。
2021 年店匠科技整个产品研发团队面临水平拆分的组织机构调整,将原来整个研发团队拆分成若干产品线,各个产品线都有各种职位的补齐。大部分的产品功能都需要补齐短板,持续优化改进。技术上需要将各个团队的代码仓分拆,独立部署,以及每个产品线都需要实现 AB/ 灰度上线,形成统一的 CI/CD 流程;管理上对整个研发需要提升各个环节的效率和质量,技术栈升级,研发人员培养;业务上需要解耦各个团队,统一研发规范。
研发团队扩张、线上变更频繁
2021 年开发团队从年初的 60+ 人到年底的 180+ 人,上线发布从 Q1 的几十次到 Q4 的 400+ 次。此时,线上的 kubernetes 正在运行着 1000+ 微服务程序。不断增加的业务,不断增加的流程导致发版流程低效了很多。
系统越来越复杂、稳定性下降
业务越来越多那么系统就越来越复杂,稳定性降低也成为了不可忽略的重要问题。系统规模急剧扩张,新功能无法准确评估其线上影响以及功能上线出现的 bug,各个团队的分工越来越细,团队的边界逐渐清晰,但是各个业务线、技术线还是存在直接或非直接的耦合的关联。例如:1、基础服务团队发版 API 有变更,调用方不知情都容易导致出现问题。2、无法准确评估每次发布前后各项业务关键指标的变化,这里说的关键指标主要是整个电商购物流程中的各个环节的转化,对于电商 SaaS 平台,我们一直把这些指标当做产品竞争力的重要组成部分,曾经有一段时间,关键业务指标转化率有时失守,通过监控内部、外部环境以及发版日志,事后去找原因也往往已经造成了影响。久而久之,形成了“上线忧虑症”,影响整个团队的士气。
新需求决策变难
产品新需求决策变难,用户增长压力变大,不同于产品从 0 到 1 解决功能有无的问题。产品调研无法获取一手数据以验证假设是否成立,需要不断地实验去验证假设。即便是已经有非常明确的需求落地,项目上线发布后没有足够的数据可以支撑功能对业务指标的影响。
挑战的真面目
综上所述,2021 年我们面临的真实挑战是根据如下需求形成一套持续交付系统:
(1)核心转化率指标与服务稳定性,毕竟质量与稳定永远是首要保证。
(2)迭代速度需要持续提升,发布频率越来越高,效率不能太低。
(3)最低成本验证假设,降低决策成本。
持续交付核心目标
解决挑战的依赖
持续交付
如果想要满足“迭代速度持续提升,发布频率越来越高,效率不能太低”这个需求,那么自动化的持续交付肯定是不能少的。持续交付一直以来是一个统称,其实具体一点应该分为持续集成(Continuous Integration)、持续交付(Continuous Delivery)、持续部署(Continuous Deployment)。
持续集成
(CI)在传统的软件开发中,集成过程通常发生在每个人完成工作后的项目结束时。而整合集成的过程通常需要数周或数月,并且可能非常痛苦。持续集成是一种将集成阶段置于开发周期早期的实践,以便可以定期的构建、测试和集成代码。
CI 意味着多位开发者可以在不同环境不同场景对同一个产品进行代码编写,并将代码集成到代码仓库,然后根据各自编写的部分在 CI 的服务器当中进行构建和组合,并通过单元测试来检查代码是否按照开发者期望的方式运行,以便开发者进行后续的开发。
持续集成
持续交付
(CD)在持续集成的过程中我们只是考虑了单纯的开发环境,持续交付与持续集成的区别在于多个不同环境下的体现,持续交付意味着开发者对代码进行更改、集成和构建时,还需要在类似于开发环境的其他环境进行同样的构建、集成、测试等操作。我们将这种部署到不同环境并在不同环境上进行测试的过程称之为部署管道(deployment pipeline)。部署管道通常会具有开发环境、测试环境、暂存环境以及生产环境。
持续交付
开发者在不同的环境下完成部署、测试并且程序可以正常运行,会使得开发者越来越有信心完成交付工作,更重要的是当程序完成当前环境下的测试并入到下一个环境后进行测试或运行发现异常时,也可以快速定位问题、解决问题。
持续部署
对于成熟的部署管道来说,最后的阶段是持续部署。作为持续交付——自动将生产就绪型构建版本发布到代码存储库的延伸,持续部署可以自动将应用发布到生产环境。由于在生产之前的管道阶段没有手动门控,因此持续部署在很大程度上都得依赖精心设计的测试自动化。
实际上,持续部署意味着开发人员对应用的更改在编写后的几分钟内就能生效(假设它通过了自动化测试)。这更加便于持续接收和整合用户反馈。总而言之,所有这些 CI/CD 的关联步骤都有助于降低应用的部署风险,因此更便于以小件的方式(而非一次性)发布对应用的更改。不过,由于还需要编写自动化测试以适应 CI/CD 管道中的各种测试和发布阶段,前期投资还是会很大。
持续部署
发布工程
单纯的持续交付并不足以支持整个公司持续交付系统的体系设计。所以我们又研读了 Google 运维团队大牛编著的《SRE:Google 运维解密》。在《SRE:Google 运维解密》一书中阐述了大量关于运维可靠性的介绍。其中有专门的章节介绍发布工程。“发布工程 ( Release Engineer ) 是软件工程内部的一个较新、发展较新的学科,专注于构建和交付,为保障服务的可靠部署与变更需要制定可靠的发布流程,SRE 需要保证二进制文件和配置文件是以一种可重现的、自动化的方式构建出来的。”。
持续测试 ( 一万次实验法则 )
想要满足“最低成本验证假设,降低决策成本”,那么就要进行各种测试。业界有很多对于实验比较重视的企业例如亚马逊和 Facebook。他们也有两句经典的名言:
亚马逊 CEO 贝佐斯说“亚马逊的成功是每年、每月、每周、每天进行多次实验的结果。”。Facebook CEO 扎克伯格也说过: “ 我最为自豪的事情之一是我们成功的关键在于测试框架...... 在任何时候,都不只有一个 Facebook 版本正在运行,而是一万个左右 ”。
国内我们熟知的字节跳动,A/B 测试视为基础工具单日新增实验多达 1500 之多,累积 A/B 测试已达 70w+,真正做到数据驱动决策。下图展示了 Facebook 如何使用多次假设反复快速收集数据来快速迭代产品。
Facebook 假设驱动开发
业务指标监控
“核心转化率指标与服务稳定性,毕竟质量与稳定永远是首要保证”,这也是我们的需求之一。要做到这一点,就需要对持续发布系统增加服务器数据收集和分析的功能。Netflix 通过 canary 发布,将 baseline 版本和 canary 版本分别部署在等量的服务器资源上,通过逐步放量收集分析反馈监控数据来判断上线质量,减少上线风险。
Canary 发布
动化 Canary 分析 (ACA) 平台
性能指标监控
Prometheus 是一个开源的系统监视和警报工具包,也可以支撑我们“核心转化率指标与服务稳定性,毕竟质量与稳定永远是首要保证。”这个需求。Prometheus 在记录纯数字时间序列方面表现非常好,既适用于面向服务器等硬件指标的监控,也适用于高动态的面向服务架构的监控。多维度数据收集和数据筛选查询语言也是非常的强大。服务出现故障时,它可以使你快速定位和诊断问题。它的搭建过程对硬件和服务没有很强的依赖关系。Prometheus 不适用场景 Prometheus 它的价值在于可靠性,可以随时访问和查看系统服务各种指标。对于统计数据 100% 精确,并不适用,比如实时计费系统。
Prometheus
Prometheus 的工作流程:
1、Prometheus 服务器定期从配置好的 jobs 或者 exporters 中获取指标数据,每个抓取目标需要暴露一个 http 服务的接口给它定时抓取。
2、Prometheus 服务器在本地存储收集到的度量数据,并对这些数据进行聚合。
3、运行已定义好的 alert.rules,记录新的时间序列或者向告警管理器推送警报。
4、告警管理器根据配置文件,对接收到的警报进行处理,并通过 email 等途径发出告警。
5、可通过自带 WebUI、或 Grafana 等图形工具获取到监控数据,并以图形化的方式进行展示。
店匠解决方案
基于店匠科技团队的研发背景,以及业界的优秀实践,我们需要构建一套快速稳定的发布系统,同时也需要 AB 实验平台加以验证产品技术的各种假设场景。基于现有的技术架构和基础服务设施,我们自研了一套能够做到请求分流、数据收集、数据分析、异常报警、全自动无人值守、ABTest 的发布系统,其整体架构如图:
店匠科技发布系统架构图
配置中心:负责存储基本的上线信息,版本信息,分流比例等配置。
Gateway:负责读取配置中心的配置,将流量按比例标示为 A 或者 B 版本,下发 Http Header 到下游服务,同时在浏览器中存储 Cookie 标示分支。
浏览器:根据标示分支将数据上报到数据仓库。
服务间调用:经过内部服务调用网关,网关同样根据 Http Header 转发到对应的服务。并将数据相关指标上报到 Prometheus
数据分析平台:聚合数据仓库和 Prometheus 的服务端监控数据,自动分析数据。
请求分流
能将服务准确的转发到制定的版本中,请求分流包含网关的请求转发和内部服务调用,具体而言我们会为用户生成随机标示,结合业务分层然后 hash 取余得到用户分桶,根据桶分布来控制流量比例。
请求分流
Gateway 转发服务会带上 Header x-rf 标示 rf 是 release feature 的简称,标示版本特性,也就是用户所在的分支。服务会转发到 traefik 上。分支的版本匹配到 Header:x-rf,将服务路由到对应的服务上。
用户数据收集
数据收集流程
Gateway 会在浏览器中存储 Cookie(user_id 是用户标示,user_tag 是标示当前所在分支),在所有的事件上报中都会带上 user_tag,一个用户可能会参与不同层的实验,多个实验的 tag 会以逗号分隔一并上报到数据仓库中。
全自动:
持续部署
结合已有的 CI/CD 流程,发起上线部署时,将 canary 版本和 baseline 版本部署到等量服务器资源,这样是为了更清晰准确的对比服务的性能表现。在发布系统完成放量分析时,整个发布流程会自动全量上线完成整个上线流程。
持续部署
自动放量
当服务部署好后,配置中心的调度程序就会自动启动放量,放量分为若干阶段,每个阶段放量的比例逐渐放大,每个阶段会定时监控关键指标是否偏差过大,一旦发现出现过大偏差,及时撤回流量,上报风险警示。
业务分层
实验分层并行是保证效率的基本要求,在发布系统这个场景,业务分层相对比较简单,因为通常我们都认为各个微服务应用都是高内聚低耦合,不同服务可以认为是在不同层。层之间的流量正交。分层是根据服务字典各个位 0、1 值相加得到。在放量的过程中,如果服务之间有交集,流程是不能重叠的,用户经过某一个服务的时候只能到达一个特定的版本。
多上线并行,自动调度
按部署服务字典计算 layer
分层流量原则
指标
性能指标
性能指标
我们从 Prometheus 收集到网关服务器 pod 的 100+ 种类指标,每个指标都会得到 3 条折线,分别对应的是生产环境、baseline 版本、canary 版本的数据展示,通常我们会对比 baseline 版本,canary 版本指标,如果 canary 版本指标使用 U 检验出现显著差异,大概率认为新版本的上线版本存在性能下降的可能性,如图指标,橙色的 canary 版本的平均响应时间已经明显变慢,本次上线将会停止。
护栏指标: 确保上线数据可信
平台本身的可靠性、准确性是护栏指标,确保指标可信,我们需要将 SRM 样本偏差比例维持在 0.2% 以内。这里的 SRM 最简单,如果在服务端分流比例是 5:5,收集上来的的 UV 数是不是可以精确到 5:5,如果偏差过大,实验基本等同作废,数据不具有说服力。除了 UV,还需要细分维度,用户的语言、国家、浏览器等指标都需要下钻。新老客户的比例是防止实验残留影响。对于平台自身的迭代发布,需要做一轮 AB 实验收集数据确保无问题才可以接入真实的上线。
服务端指标
服务端指标包括服务平均响应时间,Http 状态分布、Http 接口响应慢请求比例。考虑上报数据方差比较大,还要需要根据不同的分位值来进行对应的分析。
用户行为指标
用户侧的主要感知指标分别是 LCP(Largest Contentful Paint)页面最大元素的渲染时间分位置、服务端响应时间分位值、响应接受时间分位值、JavaScript 报错的数量等相关指标。
历史经验传承
有些指标可能比较专业,数据工程师不能直观地看出优劣,我们可以从历史实验数据中进行对该指标的差异排名,如果排名靠前靠后说明指标存在差异,不断地积累历史数据为数据分析工程师提供更多的参考信息。
上线与 AB 实验
发布系统也可以用于 AB 实验,AB 实验也需要构建版本发布,不同的是 AB 实验通常需要全量上线,需要的流程更多,对于上线发布,数据重点监控的是有无负面影响,AB 实验更多需要关注假设是否成立,对业务指标有无正面影响。
总结
通过新平台我们很好地解决了遇到的问题和考验。依靠请求分流、数据收集、数据分析、全自动、ABTest 等新特性,我们显著地降低了事故的数量,确保了上线质量、提升了上线效率,有效地支撑了产品决策。
问答分享
市面上的 AB 测试工具产品存在哪些问题?
答:在决定自研平台之前,我们调研过市面的 AB 测试以及用户增长平台,存在 2 个比较大的问题:
1、绝大多数平台在修改 web 前端页面时会下发 JavaScript,HTML,CSS 片段,在 JS 执行的时候页面会出现闪烁,影响用户体验。
2、大多数平台在后端需要集成 sdk,二次开发工作量不小,如果是自研,不存在侵入性,只需要构建出正常的迭代版本。
分流方式应该如何处理?
答:不推荐在前端注入额外的 js 去修改页面,最好的方式是在服务端做直出,这样对用户的影响能降到最低。不推荐不同分支有不同的状态数据,比如有不同的数据库、redis、清理兼容工作会比较繁琐处理不好容易出问题。
对于后端服务,线上的版本会存在多个版本共存,我们是在技术评审中需要明确的定义部署方式,以及是否有共存问题。
对研发基建有哪些挑战?
答:确实挑战比较大,服务的部署方式,尤其是 web 前端的部署方式五花八门,要做到不同版本使用不同的版本,需要大量的额外的工作。
监控指标工作量也很大,指标很多,本身还在不断规范统中,需要收集到这些指标,不断调整报警阈值,及时停止上线。
关于店匠
店匠科技(SHOPLAZZA)是一家专注为全球 B2C 电商提供产品和技术解决方案的公司,一直以来致力于与更多的全球开发者一起,帮助商家实现全球商业成功。近期完成了总额 1.5 亿美元的 C1 轮融资。
参考文献:
《The Product Managers’ Guide to Continuous Delivery and DevOps》
《店匠科技交付体系探索以及实践:无负担发布体验》阳衡锋
评论