转转QA 代码 diff 服务改进方案

庄锦弟 for 转转QA · 2021年09月23日 · 最后由 陈恒捷 回复于 2021年09月24日 · 3815 次阅读

作者 | 王悦

背景

代码 diff 系统,是增量静态代码扫描,增量代码覆盖率,增量接口扫描等众多基础系统的依赖方,其稳定性和性能直接影响整个工作流。随着调用量的升高,尤其是转转增量代码统计率功能成为 beetle 流程中的卡点,代码 diff 作为基础数据提供方,渐渐暴露出了性能和前期设计方案的问题。

原始实现方案的流程如下图:

存在问题

1、需要将 gitlab 上的代码分支克隆到本地服务器(分支新建时提前预热),通过 jgit 的接口进行 diff。但是当代码仓库比较大,在上面提到的异常流程时,仍然要 clone,拉取时间长,影响接口性能。

2、在本地服务器 diff,需要加锁,导致不支持同一个代码仓库的并发。

优化方案

1、空间换时间

仍然使用代码 clone 到本地的方案,但是按照分支维度放置代码。这样能解决不同分支间的并发问题。优点:去除了本地 git 锁判断过程,逻辑相对于原来改动小,实现成本小。不足:相同分支的情况下,仍然需要在平台上对 jgit 的代码处理逻辑加锁。锁冲突的概率和代码 git pull 的时间成正比。并发较高的情况下,失败和等待的时间仍然不可接受。
2、去掉 jgit

使用工具 java-gitlab-api,调用 gitlab 原生的 api 获取 diff 的差异,并发和性能都很稳定,我们采用了这个新方案。上线初期阶段表现是完全符合要求的,也在想之前的同事为什么没有采用这个方案?

新的问题

使用过程中调用方反馈,diff 不准(gitlab 原生接口还不准?)。经过排查发现,gitlab 的接口没有忽略空格的选项。而 jgit 可以使用 WS_IGNORE_ALL 等参数,略掉空格等格式的变更。业务方需要忽略掉只是变更了空格和格式的内容。这样增量统计才准。

方案补:

经过一番调研之后,我们发现 gitlab 的 diff 接口是没有额外的参数的。所以我们决定在 gitlab 的 diff 结果上,增加一个对比补偿方案。并且希望处理结果尽量和 jgit 处理结果一致。经过调研和多次尝试,最终确认使用开源工具 java-diff-utils 对 gitlab 返回的数据格式进行预处理,同时使用和 jgit 同样的 diff 算法 HistogramDiff 来保证数据的一致性。

其他问题:

1、使用过程中发现部分大文件获取差异内容为 diff 为空。原因是触发了 Gitlab Diff 数据大小限制。参考 Diff limits administration | GitLab 修改。
2、上面的方案,在 diff 文件量很大的时候,会触发性能问题,使用多线程处理。

总结

在使用 gitlab api 的方案过程中,我们进行了很多的尝试,走了很多的弯路,最终达到现在的效果。保证作为基础中的基础系统--diff 系统的稳定和性能。各位朋友如果有其他的方案和思路欢迎在评论区留言,咱们一起交流下。

参考资料

1,https://github.com/java-diff-utils/java-diff-utils
2,https://docs.gitlab.com/ee/api/

往期精彩文章回顾

转转 QA-2021 上半年文章集锦

转转 2022 年校园招聘

测试小白 - 进阶论

开学福利!一大波测试人专属学习资料,解锁工作新姿势

共收到 1 条回复 时间 点赞

业务方需要忽略掉只是变更了空格和格式的内容

这个细节挺不错,我们之前没留意到。确实需要加上。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册