《卓越成效的程序员》是若干程序员系列书籍我比较喜欢的一本,类似的还有《卓越程序员密码》等。《卓越成效的程序员》高明之处是不仅仅给出原则,还大谈工具和代码,这如同诸多鸡汤文在”布道”的层面之下实战干货,深得广大从业人员喜爱。
持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽快地发现集成错误。许多团队发现这个过程可以大大减少集成的问题,让团队能够更快的开发内聚的软件。
我们先来看这样一个例子:某团队在具体部署SystemP的持续集成的时候发现一个问题, SystemP重度依赖下游系统SystemQ,而SystemQ系统开发环境的不稳定导致CI经常大量失败,后面做了一个工具能够自动采集对下游成功调用的结果转换成缓存文件,后续的CI都使用这分生成的缓存文件,自动完成了对下游的隔离,极大的提升了CI稳定性。解决方案如下图所示:
在上图中,当内部节点C依赖下游系统(比如SystemQ),为了隔离下游系统的影响,开发了一个“mock拦截器”。mock拦截器实现思路如下图所示:
如上图所示,通过“mock数据是否存在的判断”,如果存在相关数据,直接从缓存中获取。
我们再来看一个场景。在SOA架构或者微服务架构中,联调是一个比较麻烦的事情,手工联调需要上下游多个系统约定时间,一起配合。好一点的做法是下游系统自己构造本地请求来模拟RPC调用,但是笔者遇到过这样的系统,这个系统是一个规则决策类系统,上游系统大约有20个,各自场景用例包括参数的不同组合达到10万这个级别,构造本地测试用例覆盖难度极高,且不易持续维护。于是团队同学就做了一点创新,思路也比较简单:做一个工具能够自动打印历史请求,然后通过工具平台将打印的请求重发到指定的服务器上, 提升了研发效率。
如上图所示,上游系统联调的时候调用服务接口,这个时候工具进行请求拦截,把上游请求序列化并保存下来。那么在下游要触发验证的时候,可以通过“重发工具平台”查找对应的日志,完成输入的触发。另外,在做回归测试的时候,采用类似的方法,可以从线上环境的用户真实访问日志提取用例导入到线下用例环境。
我们再看一个case,就是系统迁移,系统迁移往往涉及到多个烟囱型架构迁移到平台型架构,或者若干类似职责的系统统一到一个平台。一种常规的做法是先观察对比、再逐步切流、再下线老系统。笔者所在项目团队就曾开发过支持新老系统切流对比的工具。
为了确保新老服务结果的一致性和正确性,开发了一套切流对比工具,能够自动将一个接口的流量copy一份到另一个对应接口,执行完成后对两个接口的结果进行详细比对,验证正确性,在业务场景复杂的业务系统上,没有类似的工具保障,很难保证不出问题。该工具的实现示意图,如下所示。
随着工具化思路的深入人心,各个产品、各个团队都会构建处理特定问题,或者相对宽泛领域的问题。这时候为了避免重复建设,应该进行相应的治理和统筹。笔者列举一些似曾相识的场景。
场景一:研发小李需要解决分布式系统的用例沉淀的问题,他做一个线上线下日志迁移的工具。
场景二:研发小周为了解决联调成本高,时间要求的问题,开发了前文介绍的“重发”工具平台。
场景三:SOA架构下,排查问题需要登录不同的系统去查看对应的日志文件,成本高,工具团队开发了一个基于traceId的日志关联工具。
场景四:测试工具团队开发了一个叫“望眼镜”的工具用于快速定位SOA架构下系统的复杂依赖关系中error的传递情况,并用时序图展示。
场景五:在优惠场景下,由于业务复杂度、优惠规则复杂度等各种原因,用户对于一个平台的支付工具使用存在认知偏差,对于支付的优惠券、红包和支付顺序可能存在疑惑,往往通过客服渠道反馈。客服一般求助产品经理或者技术同学,最终技术同学通过日志及数据库结合类似traceId进行排查。由于类似的查询场景比较高频,技术同学研发了一个平台,把查询的结果翻译成客服可以明白的业务语义内容,可以供客服自助查询。
场景六:工具团队开发了一个故障排查模块,因为SOA架构下,定位问题基本靠吼,比如交易大盘下跌了,各变更系统owner都会去看自身系统的错误情况,然后去人肉关联思考故障原因。能不能把这些经验通过一系列规则脚本承担下来呢?
通过6个场景,我们可以总结出下表。以上场景其实是冰山一角,如果在上千人的团队大团队,对于各种差异化的场景不可胜数,因此统一规划工具势在必行。
通过以上分析,可以得到一些阶段性结论。比如“故障排查模块”用于线上,而且用于即时的故障定位,那么日志数据不用单独存储,重点在快、准,这个工具是单独一套架构体系。而“望眼镜”这个工具如果也是瞬间定位,那么完全可以复用“故障排查模块”的核心能力,“系统调用时序图”是增强的一个特性而已。
结论:统一工具平台,可以考虑不同工具层次,能复用的尽量复用,并且注意平台的开放性,比如插件化能力。而对于目标和实现方案差异很大的平台,则可以分别建设。比如“业务优惠查询工具”需要处理几天甚至1个月前的用户投诉,在数据上面需要从日志提取、转换和专门存储。而“故障排查模块”在于解决故障的快速定位问题,超过1个小时的定位无法容忍,日志文件默认7天,则不需要把目标数据从日志提取,专门存储。这是2个工具最大的差异,应该分别建设为宜。
PS:本文选自右军专栏《20年职业50个思考与洞察》