ZKX's LAB

团队重构大型内部工具的经验教训

2020-10-21新闻17

作者丨Junade Ali,Peter Weaver

译者丨足下

策划丨蔡芳芳

本文介绍了 Cloudflare 研发团队对内部工具 Crossbow 成功进行优化重构的过程,并分享了一些有益的经验。

Cloudflare 公司的服务网络现在已经扩展到了 90 多个国家的 200 多个城市中。产品、技术支持和运维等项目组的工程师们经常需要诊断某地或某几台服务器的网络问题。

Crossbow 就是用来解决这个问题的内部工具。有了它,Cloudflare 的技术支持工程师们就可以运行各种命令(比如 traceroute、CURL 和 DNS 请求等)来分析问题,并用各种定制工具来定位产品的功能和性能问题。

Cloudflare 的一位技术经理在去年 9 月提出,希望把 Crossbow 从产品工程团队转交给支撑运维团队。这个工具的受关注度很高,在此之前已经在多个工程团队之间转交过了,但并有开发出什么重要的新特性来。

Cloudflare 的支撑运维团队一直与技术支持工程师们紧密合作,为提高效率,他们不断地开发各种诊断工具和自然语言处理技术等。因为有这样的基础,所以最终大家一致认为,接过维护 Crossbow 的重任,支撑运维团队是最适合的团队。

从 Sisyphus 身上学到的

在项目移交并征求改进意见的时候,一位系统可靠性工程团队的经理建议大家读一本书:《社区驱动软件的案例研究》。对于每一位在考虑开发内部工具,或者为类似工具做贡献的人来说,这本书都非常值得一读。书中解释了为完成相同的目的,为什么不同的自治团队会开发出多个不同的工具,以及这样的问题该如何避免。书中还讲到了要使用这样的工具所要面临的挑战和可采用的方法,尤其是使用这样工具的工程师们可能要改变习惯时。

我们从书中学到了许多很好的方法来帮助我们接管 Crossbow,并对这个大型内部工具开始进行重构和翻新。这篇博文可以做为类似指导书的补充篇,并提供了一些更切合实际的建议。

关于 Cloudflare 支撑运维团队的工作,在 SRECon 大会上的演讲“支撑运维工程:把开发者的成果部署到成千上万的服务器上”已经谈了很多,因此在这篇博文中就不过多涉及了。Cloudflare 支撑运维团队所采用的软件开发方法与极限编程的方式非常接近。

瘦身

Crossbow 有两种使用方式:命令行和仅供内部使用的图形化界面,后者主要是 Cloudflare 的技术支持工程师们在使用。很明显,同时维护两种操作接口会给我们的改进工作带来巨大负担,所以我们决定废弃一个。这样我们就可以将所有力量集中于一个平台,从技术、可用性、功能等各方面做出重大改进。

我们向工程、运维、解决方案和技术支持等团队发起了一次调查,请大家反馈是怎样使用这个工具的。调查让我们可以了解到各个不同团队使用这个工具的方法,这样的信息至关重要。同时在我们废弃某个接口之前,大家都会知道我们已经充分考虑了他们的想法。我们不仅调查大家喜欢哪种方式,还会问他们觉得哪种方式对于他们来说是非常必要的,同时要提供理由。

喜欢通过网页使用工具的人给出的理由是工具维护团队没能提供足够的文档和培训。而喜欢命令行方式的人则觉得命令行方式对于他们的工作来说至关重要。产品工程团队的工程师们在工作中不会经常用到 Crossbow,但有些人觉得 Crossbow 对他们的工作来说非常重要,他们希望可以来把一串串的命令写到 shell 脚本里,从而让自己的工作自动化起来。

从技术上来说,图形化用户界面是用 Java 写的,还需要有个 API 网关服务,它要把 HTTP 请求转换成带配置参数的 gRPC 请求,再完成进一步的调用。命令行方式则直接与 gRPC API 打交道,因此这个系统更简单。Cloudflare 支撑运维团队的主要工作内容是系统工程项目,使用图形用户界面并不方便,因此废弃它也主要是考虑了要让我们的工作更方便。

我们新创建了一个内部的 Crossbow 用户讨论组,组织了一些培训,编写了新的文档,提前发出了废弃图形化界面的通知,并废弃了相关服务的源码。我们同时改写了命令行方式的帮助信息,简化了使用方式。这个小改动工作量不大,却极大地提升了用户体验。

用 Cloudflare Access 改进收发方式的架构

Crossbow 的架构是许多年前设计的了,这是我们遇到的首要困难。gRPC API 可以在 Cloudflare 的边缘网络运行命令,但它要用到一个配置管理工具,而后者是系统可靠性团队想废弃的东西。事实上 Crossbow 也是它的最后一个使用者了。

为此我们特意去了一趟新加坡,拜访了当地的系统可靠性团队。团队成员们对 Crossbow 表现出了极大兴趣,希望能理解它是怎样工作的,以及他们可以怎样为这个工具添砖加瓦。我们在会议上介绍了当前的架构。当地同事则非常积极地就如何处理广域网络的稳定性、如何从旧方式中脱离出来等问题给出了许多建议。会谈给了我们许多宝贵的启示,让我们知道了常用的技术方案可能会在怎样的场景下出问题,从而可能会需要技术支持工程师们求助于系统可靠性团队。

我们决定采用一种比较简单的收发管道。边缘网络团队会提供一个 gRPC 守护程序,它负责接收新任务并执行,然后把执行结果发回给另一个 API 服务,后者会转发给任务的调用者。

对于 API 服务与客户端或边缘网络之间的安全认证问题,我们实现了一个 JWT 认证方案。对于命令行方式的使用者来说,认证是通过访问 Cloudflare Access 后面的一个 HTTP 端点来完成的,它会给客户端提供一个向 gRPC 认证的 JWT。具体的方案类似下面这样:CLI 通过 cloudflared 向认证服务器发出请求;认证服务器返回签名后的 JWT 令牌;CLI 带上 JWT 认证令牌向 API 服务发起 gRPC 请求;API 服务用公钥对令牌进行验证;

gRPC API 端点是放在 Cloudflare 内网的,因为用户已经用 Cloudflare Access 认证过了,所以我们不必再要求用户一定要先连公司的 VPN,然后才能使用这个工具。新的认证方式,以及单一的用户接口,让我们可以对工具的指标和使用情况进行收集,从而进一步做出改进。

风险管理

风险是工程专业人员所从事的活动所固有的,这意味着专业人士将会在管理和限制风险等方面发挥重要作用。——风险指引,工程委员会

管理风险对于任何工程项目来说都是至关重要的。但对于不同的工程项目,要管理的风险也不一样。可用性对我们来说并不是最重要的方面,因为工具不可用时技术支持工程师们可以求助于 SRE 团队。Crossbow 最大的风险在于 Cloudflare 网络的安全性,不能让它影响其它服务的可用性。因此我们有计划有步骤地改进了它的隔离性,很早就请信息安全团队参与进来,帮我们制订规范,并对新的收发管道进行代码审查。对于由此而引入的可用性问题,我们主动与支撑团队和内部的 Crossbow 用户组进行了沟通,向他们解释了存在的风险和这样做的初衷。

反馈、构建、重构、度量

Cloudflare 的支撑运维团队采用极限编程的方式工作。极限编程的一个关键特征就是测试驱动开发,这也被称为“红 - 绿 - 绿”模式或“红 - 绿重构”。工程师先用测试案例表述需求,然后写代码通过测试案例,再在交付软件之前对代码重构,来提高代码质量。

在刚接手这个项目时,Cloudflare 的支撑和 SRE 团队都在忙 Baton 项目,它的目标是让技术支持工程师们尽可能多地解决用户问题,避免事事上交给 SRE 团队处理。

努力初见成效,他们整理出了非常宝贵的素材,正好可以做为 Crossbow 项目的功能需求列表。我们在 JIRA 上关联了所有需求,并提高了优先级,用测试驱动开发的方式实现这些需求,还引入了持续集成的方法。而且在功能发布之后,我们会用非常严格的方式对它们进行评估。我们增加了许多简单的功能,比如支持 MTR(一个 Linux 网络诊断工具)、提供对不同 CURL 标志位的支持等,这些都提高了易用性。

我们也支持在其它团队维护的工具中嵌入对 Crossbow 的支持,帮助他们维护这样的工具,并把功能提供给 Crossbow 的用户。提供了更好的开发环境和文档,我们就可以驱动产品工程团队开发功能,与客户支持团队开发的功能互为补充。

我们最后接管了许多技术支持工程师们维护的工具,弄清楚了哪些 Cloudflare 配置被传递给了哪些 URL,哪些可以用于分布式性能测试,等等。然后我们将这些工具废弃掉,把它们的功能融合进了 Crossbow。由另一个 Cloudflare 团队维护的名叫 Edge Worker Debug 的工具也被我们融入了 Crossbow,然后那个团队就把他们的工具废弃了。

成果

在 2019 年 12 月 16 日到 2020 年 1 月 22 日我们对工具做用户分析的期间,Crossbow 的使用量增加了 4.5 倍。这么大的增幅仅仅发生在四个星期内。我们只是为这个工具增加了许多大家最想用的功能,因此就在技术支持工程师的群体中快速推广开去了。

还有一点非常关键,我们引入“执行了多少次检查”这个数字作为一个指标,来衡量这个工具到底多有用。比如,在 1 月 27 日开始的那个星期里我们看到单个用户的使用率没有什么意外的增长(考虑了稳定使用情况下的正常波动,一般是与上周相比大概有 14% 的使用率增长),但在相同的时间段里,测试的运行数量却增长了 2.6 倍,这恰好与许多高使用率的新功能引入的时间段相同。

结论

砍掉了需要大力维护却价值极低的功能,又进行了大刀阔斧的重构,我们最终得以极大地提升 Crossbow 的代码质量,提高交付速度。再引入衡量使用率的功能,建立有效的渠道接收用户的功能需求,还有测试驱动开发的模式,我们大大地提高了工具的使用率。工具整合减轻了整个公司内部开发支撑工具的工作量,我们得以为技术支持工程师们提供相同的开发框架,让大家使用相同的功能。在这个项目里我们有两点特别的收获。首先是在认真有效的沟通的前提下,削减功能竟然可以提高使用率。旧版的 Crossbow 也带有网页版的图形化用户界面,但它并没有提供什么 CLI 不具备的功能,还因此带来了许多的维护代价。废弃了图形化界面,我们的技术债务就大大减少了,因此可以把精力投入更加重要的功能,提高交付速度。这么做需要极高的沟通技巧,要与受此决定影响的人做好有效的沟通。

其次,工具开发的效果主要是看用户口碑,缺乏客观的评估手段。增加日志主要是为了安全审计的需要。建立用户反馈渠道是至关重要的,必须有客观的方式来衡量新功能有多成功,以及它是怎样为用户所用的。有效的评估可以影响将来对工具的决策,而且从长远的角度来说,关于工具使用情况的数据会比功能自身更重要。

作为一个CTO,我为什么反对“平台团队”

#技术编程

qrcode
访问手机版