build 之前执行task-ag凯发k8国际
base
基础设施部分,项目发布在中国区亚马逊云,使用了aws的容器服务(ecs)、容器注册表(ecr)、对象存储(s3)、弹性计算(ec2)
源码管理使用atlassian出品的bitbucket,一款git体系的代码仓库
ci/cd使用jenkins与pipline实现与维护
项目开发语言为nodejs
项目代号salmon
项目打包&发布使用npm&docker
一、标准的发布流程
二、症结反馈
同事a:“目前自动化的ci/cd流程在线上环境比较缓慢,可能拖累开发测试工作,请寻找一些优化点”
同事b:“我的项目在本地打包只要一两分钟,但是线上构建流程要花10 分钟”
三、成因分析
查阅jenkins console output && 分析jenkin blue-ocean的时间统计,主要分为三个关键步骤:
stage{'build'} 编译代码 // > 10min
stage{'publish'} 推到仓库 // < 10s
stage{'deploy'} 运行服务 // < 1min
随后继续分析“构建”这一步,时间消耗在docker build,进一步分析各个step,发现npm run build消耗了最多时间,约为9分钟
刚刚提到,我们线上发布流程是容器化的,包括jenkins的slave,也是在ec2虚拟机上面启动的jnlp-slave-container,再执行docker build命令,编译过程写在dockerfile当中。
与开发工程师本地构建这一过程相比,容器化的ci流,每一次构建,它的基础设施都是纯净的、无状态的,除了推送到远端的image也是没有文件留存的。即传统基础设施与容器化纯净环境的差异,可能就是build速度差异的关键。
四、问题复现
我选用了一台ec2(2核8gb),用于复现非容器化的构建流程并统计耗时,模拟开发者在自己的mac开发环境从源码到build的过程。
step1.
$ mkdir /code
拉取最新slamom项目代码,执行npm install,随后执行5次npm build,初次build约8分钟,随后的4次为2分半。
step2.
在同一个项目目录(/code),回滚至5个版本前的salmon代码 git reset --hard head^5;
执行npm install,随后执行5次npm build,初次build约1分钟,随后的4次为1分钟。
step3.
回复至第一步的最新版代 git reset --hard head;
执行npm install,随后执行5次npm build,初次build约2分半,随后的4次为2分半。
下图为脚本输出记录。
1~5 step1;101~105 step2小结:在已build过的项目目录进行后续build,会大大减少这一过程耗时,是否是因为生成了编译的缓存文件?
step4.
复现与审查ci流程,主要为3步,多次复现发现项目目录容量增长如下
- 拉代码 # 14mb
- npm install # 434mb
- npm run build #525mb
已知.next/目录下为npm run build编译后的成品项目代码,删除这部分后,有470mb
经过多重文件对比,定位到在编译后的项目中,node_modules/目录下会有一个.cache 目录
多次调试,验证了build前后差30mb文件的问题,确实是在 .cache 目录中
将.cache目录的内容应用到已执行npm install未build的目录,有以下场景:
- 同版本号的代码,build时间 8min → 2.5min
- 临近两三个版本号的代码,build时间 8min → 4min
- 差较大版本号的代码,build时间仍为 8min
五、优化设计
接下来考虑的是如何将这个目录,或称缓存池,维护和利用起来?考虑ci流基本都在小版本号之前变更,决定将这个缓存目录维护在线上,build之前拉取,build之后推送。
我使用了aws的s3服务,s3有一个目录同步功能(sync)
文档地址:https://docs.amazonaws.cn/cli/latest/userguide/cli-services-s3-commands.html
# s3 sync 命令使用如下语法。可能的源-目标组合有:# 本地文件系统到 amazon s3# amazon s3 到本地文件系统# amazon s3 到 amazon s3$ aws s3 sync- 上一篇:
- 下一篇: