html
build 之前执行task-凯发ag旗舰厅登录网址下载
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在ec2测试机上运行的结果:
六、优化编译脚本(即dockerfile)
改造了原有的node-builder镜像,添加了aws cli工具用以操作s3,imageurl:
***.http://dkr.ecr.cn-northwest-1.amazonaws.com.cn/node-builder-with-awscli:normal
改写后的dockerfile摘录如下:
# 添加了build过程与缓存池的pull&oush交互-20191213 from ***.dkr.ecr.cn-northwest-1.amazonaws.com.cn/node-builder-with-awscli:normal as builder# create app directory workdir /usr/src/app# install app dependencies # a wildcard is used to ensure both package.json and package-lock.json are copied # where available (npm@5 ) # bundle app source copy . .run npm cache clear --force && npm_config_registry=https://registry.npm.taobao.org npm install && mkdir node_modules/.cache && aws s3 sync --quiet s3://zhiwen-build-cache/salmon/.cache/ node_modules/.cache/ && npm run build && aws s3 sync --quiet node_modules/.cache/ s3://zhiwen-build-cache/salmon/.cache/ && rm -rf node_modules/.cachefrom node:10.15.3-alpineworkdir /usr/src/appcopy --from=builder /usr/src/app .#user nodeexpose 3000 cmd [ "npm", "start" ]七、验证优化效果
摘录了jenkins blue-ocean的统计,一个jenkinsfile包含4个stage的执行时间
salmon-dev-661 : stage{'build'} 耗时4m7ssalmon-dev-661 : next build 耗时2m41s对比一个未优化的ci流
salmon-dev-399 : stage{'build'} 耗时9m43ssalmon-dev-661 : next build 耗时8m4s提速效果还是比较明显的
八、关于线上缓存池
- 缓存池会越来越大,会不会反过来拖累build时间
- 设置了创建时间大于5天即删除的缓存池过期策略,看看好不好使,或把这个时间改更短些
这是当时实施留存的两个issue,根据后续的运行观察:
- 缓存池(一个s3 bucket的目录)保存了大概3000~3600个静态文件,build样本为dev环境的14个,时间均在4分半到5分钟
- sync操作需要20s~30s
- 5天的缓存池过期策略能够正常运行,也比较匹配开发周期
九、问题与总结
其他项目没有使用 .next 框架或webpack打包工具可能铺展不开这套 .cache 缓存池的优化策略。
本文使用的工具都比较简单,得益较大的是在优化探索中
- 问题采集与复现
- 数据对比
- 成因分析
- 优化方案设计
- 搜寻适合工具
- 思路举一反三
- 成果检验
这些项目工程逻辑与解决问题的思考和方法论,希望能对自己和读者都有些启发
总结
以上是凯发ag旗舰厅登录网址下载为你收集整理的build 之前执行task_一次npm前端项目的ci-build速度优化的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得凯发ag旗舰厅登录网址下载网站内容还不错,欢迎将凯发ag旗舰厅登录网址下载推荐给好友。
- 上一篇:
- 下一篇: