《Java应用提速(速度与激情)》——三、docker构建提速

简介: 《Java应用提速(速度与激情)》——三、docker构建提速

1. 背景

 

自从阿里巴巴集团容器化后,把构建镜像做为发布构建的一步后开发人员经常被镜像构建速度困扰,每天要发布很多次的应用体感尤其不好。

 

为了让应用的镜像构建尽量的少,我们几年前已经按最佳实践推荐每个应用要把镜像拆分成两部分,一部分是基础镜像,包含低频修改的部分。另一部分是应用镜像,包含高频修改的部分,比如应用的代码构建产物。但是很多应用按我们提供的最佳实践修改后,高频修改部分的构建速度依然不尽如人意。

 

现在CICD平台和集团很多镜像构建场景用的还是pouch的前身。它只支持顺序构建,对多阶段并发构建的支持也不完整,我们设想的很多优化方法也因为它的技术过于老旧而无法实施。它中很多对低版本内核和富容器的支持也让一些镜像包含了一些现在运行时用不到的文件。

 

为了跟上主流技术的发展,我们计划把CICD平台的构建工具升级到moby-buildkit,docker的最新版本也计划把构建切换到moby-buildkit了,这个也是业界的趋势。同时在buildkit基础上我们作了一些增强。

 

2. 增强

 

1) 新语法SYNC

 

我们先用增量的思想,相对于COPY增加了一个新语法SYNC。

 

我们分析Java应用高频构建部分的镜像构建场景,高频情况下只会执行Dockerfile中的一个指令:

COPY appName.tgz /home/appName/target/appName.tgz

发现大多数情况下Java应用每次构建虽然会生成一个新的app.war目录,但是里面的大部分jar文件都是从maven等仓库下载的,它们的创建和修改时间虽然会变化但是内容的都是没有变化的。

 

对于一个1G大小的war,每次发布变化的文件平均也就三十多个,大小加起来2-3 M,但是由于这个appName.war目录是全新生成的,这个copy指令每次都需要全新执行,如果全部拷贝,对于稍微大点的应用这一层就占有1G大小的空间,镜像的copy push pull都需要处理很多重复的内容,消耗无谓的时间和空间。

 

如果我们能做到定制dockerfile中的copy指令,拷贝时像Linux上面的rsync一样只做增量copy的话,构建速度、上传速度、增量下载速度、镜像的占用的磁盘空间都能得到很好的优化。因为moby-buildkit的代码架构分层比较好,我们基于dockerfile前端定制了内部的SYNC指令。

 

我们扫描到SYNC语法时,会在前端生成原生的两个指令,一个是从基线镜像中link拷贝原来那个目录(COPY),另一个是把两个目录做比较(DIFF),把有变化的文件和删除的文件在新的一层上面生效,这样在基线没有变化的情况下,就做到了高频构建每次只拷贝上传下载几十个文件仅几兆内容的这一层。

 

而用户要修改的,只是将原来的COPY语法修改成SYNC就行了。

 

如将:

COPY appName.tgz /home/admin/appName/target/appName.tgz

修改为:

SYNC appName.dir /home/admin/appName/target/appName.war

我们再来看看SYNC的效果。集团最核心的热点应用A切换到moby-buildkit以及我们的sync指令后90分位镜像构建速度已经从140秒左右降低到80秒左右

 

image.png

2) none-gzip实现

 

为了让moby- buildkit能在CICD平台上面用起来,首先要把none-gzip支持起来。

 

这个需求在docker社区也有很多讨论https://github.com/moby/moby/issues/1266

 

内部环境网络速度不是问题,如果有gzip会导致90%的时间都花在压缩和解压缩上面,构建和下载时间会加倍,发布环境拉镜像的时候主机上一些CPU也会被gzip解压打满,影响同主机其它容器的运行。

 

虽然none-gzip后,CPU不会高,但会让上传下载等传输过程变慢,因为文件不压缩变大了。但相对于CPU资源来说,内网情况下带宽资源不是瓶颈。

 

只需要在上传镜像层时按配置跳过gzip逻辑去掉,并把镜像层的MediaType

 

application/vnd.docker.image.rootfs.diff.tar.gzip

 

改成

application/vnd.docker.image.rootfs.diff.tar

 

就可以在内网环境下充分提速了。

 

3) 单层内并发下载

 

在CICD过程中,即使是同一个应用的构建,也可能会被调度到不同的编译机上。即使构建调度有一定的亲和性。

 

为了让新构建机,或应用换构建机后能快速拉取到基础镜像,由于我们以前的最佳实践是要求用户把镜像分成两个(基础镜像与应用镜像)。换编译机后需要在新的编译机上面把基础镜像拉下来,而基础镜像一般单层就有超过1G大小的,多层并发拉取对于单层特别大的镜像已经没有效果。

 

所以我们在层内并发拉取的基础上,还增加了同一层镜像的并发拉取,让拉镜像的速度提升了4倍左右。默认每100M一个分片,用户也可以通过参数来设置分片大小。

 

当然实现这层内并发下载是有前提的,即镜像的存储需要支持分段下载。因为我们公司是用了阿里云的OSS来存储docker镜像,它有很好的分段下载或多线程下载的性能。

 

4) 无中心P2P下载

 

现在都是用containerd中的content store来存储镜像原始数据,也就是说每个节点本身就存储了一个镜像的所有原始数据manifest和layers。所以如果多个相邻的节点,都需要拉镜像的话,可以先看到中心目录服务器上查看邻居节点上面是否已经有这个镜像了

 

如果有的话就可以直接从邻居节点拉这个镜像而不需要走镜像仓库去取镜像layer,manifest数据还必须从仓库获取是为了防止镜像名对应的数据已经发生了变化了,只要取到manifest后其它的layer数据都可以从相邻的节点获取,每个节点可以只在每一层下载后的五分钟内(时间可配置)提供共享服务,这样大概率还能用到本地page cache,而不用真正读磁盘。

 

image.png 

 

中心OSS服务总共只能提供最多20G的带宽,从历史拉镜像数据能看到每个节点的下载速度都很难超过30M,但是我们现在每个节点都是50G网络,节点相互之间共享镜像层数据可以充分利用到节点本地的50G网络带宽,当然为了不影响其它服务,我们把镜像共享的带宽控制在200M以下。

 

5) 镜像ONBUILD支持

 

社区的moby-buidkit已经支持了新的schema2格式的镜像的ONBUILD了,但是集团内部还有很多应用FROM的基础镜像是schema1格式的基础镜像,这些基础镜像中很多都很巧妙的用了一些ONBUILD指令来减少FROM它的Dockerfile中的公共构建指令。

 

如果不能解析schema1格式的镜像,这部分应用的构建虽然会成功,但是其实很多应该执行的指令并没有执行,对于这个能力缺失,我们在内部补上的同时也把这些修改回馈给了社区(https://github.com/moby/buildkit/pull/3053)。

相关文章
|
20天前
|
存储 数据采集 搜索推荐
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
本篇文章探讨了 Java 大数据在智慧文旅景区中的创新应用,重点分析了如何通过数据采集、情感分析与可视化等技术,挖掘游客情感需求,进而优化景区服务。文章结合实际案例,展示了 Java 在数据处理与智能推荐等方面的强大能力,为文旅行业的智慧化升级提供了可行路径。
Java 大视界 -- Java 大数据在智慧文旅旅游景区游客情感分析与服务改进中的应用实践(226)
|
20天前
|
存储 监控 数据可视化
Java 大视界 -- 基于 Java 的大数据可视化在企业生产运营监控与决策支持中的应用(228)
本文探讨了基于 Java 的大数据可视化技术在企业生产运营监控与决策支持中的关键应用。面对数据爆炸、信息孤岛和实时性不足等挑战,Java 通过高效数据采集、清洗与可视化引擎,助力企业构建实时监控与智能决策系统,显著提升运营效率与竞争力。
|
20天前
|
Java 大数据 数据处理
Java 大视界 -- 基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战(222)
本文探讨了基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战。文章分析了传统制造模式的局限性,介绍了工业互联网带来的机遇,并结合实际案例展示了 Java 在多源数据采集、实时处理及设备协同优化中的关键技术应用。同时,也深入讨论了数据安全、技术架构等挑战及应对策略。
|
20天前
|
机器学习/深度学习 人工智能 自然语言处理
Java 大视界 -- Java 大数据机器学习模型在自然语言生成中的可控性研究与应用(229)
本文深入探讨Java大数据与机器学习在自然语言生成(NLG)中的可控性研究,分析当前生成模型面临的“失控”挑战,如数据噪声、标注偏差及黑盒模型信任问题,提出Java技术在数据清洗、异构框架融合与生态工具链中的关键作用。通过条件注入、强化学习与模型融合等策略,实现文本生成的精准控制,并结合网易新闻与蚂蚁集团的实战案例,展示Java在提升生成效率与合规性方面的卓越能力,为金融、法律等强监管领域提供技术参考。
|
20天前
|
存储 人工智能 算法
Java 大视界 -- Java 大数据在智能医疗影像数据压缩与传输优化中的技术应用(227)
本文探讨 Java 大数据在智能医疗影像压缩与传输中的关键技术应用,分析其如何解决医疗影像数据存储、传输与压缩三大难题,并结合实际案例展示技术落地效果。
|
20天前
|
机器学习/深度学习 安全 Java
Java 大视界 -- Java 大数据在智能金融反洗钱监测与交易异常分析中的应用(224)
本文探讨 Java 大数据在智能金融反洗钱监测与交易异常分析中的应用,介绍其在数据处理、机器学习建模、实战案例及安全隐私等方面的技术方案与挑战,展现 Java 在金融风控中的强大能力。
|
20天前
|
机器学习/深度学习 算法 Java
Java 大视界 -- Java 大数据机器学习模型在生物信息学基因功能预测中的优化与应用(223)
本文探讨了Java大数据与机器学习模型在生物信息学中基因功能预测的优化与应用。通过高效的数据处理能力和智能算法,提升基因功能预测的准确性与效率,助力医学与农业发展。
|
存储 分布式计算 Hadoop
基于docker的Hadoop环境搭建与应用实践(脚本部署)
本文介绍了Hadoop环境的搭建与应用实践。对Hadoop的概念和原理进行了简要说明,包括HDFS分布式文件系统和MapReduce计算模型等,主要通过脚本的方式进行快捷部署,在部署完成后对HDFS和mapreduce进行了测试,确保其功能正常。
|
11月前
|
运维 监控 Cloud Native
深入了解容器化技术:Docker 的应用与实践
【10月更文挑战第6天】深入了解容器化技术:Docker 的应用与实践
164 0
|
运维 开发者 Docker
Docker容器化技术在运维中的应用实践
【8月更文挑战第27天】本文旨在探讨Docker容器化技术如何在现代运维工作中发挥核心作用,通过深入浅出的方式介绍Docker的基本概念、优势以及实际应用场景。文章将结合具体案例,展示如何利用Docker简化部署流程、提高资源利用率和加强应用的可移植性。读者将获得对Docker容器技术在实际运维中应用的全面认识,并能够理解其在提升运维效率与质量方面的重要性。