《Java应用提速(速度与激情)》——一、maven构建提速(下)

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

更多精彩内容,欢迎观看:

《Java应用提速(速度与激情)》——一、maven构建提速(上)https://developer.aliyun.com/article/1223856?spm=a2c6h.13148508.setting.14.68ac4f0elVtcZX



为保证依赖包的准确性需要将.m2隔离.即每个pod都有一个独立的.m2来volume

 

image.png

架构2.0按pod隔离.m2

 

虽然这样会浪费一些磁盘但准确性就能得到保障但产生了同一个仓库的同一个依赖会在同一个node上重复下载的问题即使2.0图示的二个pod是同一个应用的并发构建但在同一个node上面下载maven-compiler-plugin:3.8.1时要下载二次

 

所以我们继续架构演进来按app来隔离

 

image.png

架构3.0按app隔离.m2

 

但还是会存在同一个node上重复下载同一个仓库的同一个依赖文件因为appA与appB它们用的是同一个仓库因为在一个node上是不会知道在其中运行的mvn build的是同一个应用或不同应用但相同仓库或不同应用不同仓库

 

所以我们得继续演进不按应用而按仓库来隔离.m2

 

image.png

架构4.0按repo隔离.m2

 

这架构看上去感觉还可以但解决不了一个应用依赖多个仓库的问题

 

有些应用有些复杂它会在maven构建的仓库配置文件settings.xml或pom文件中指定下载多个仓库因为这应用的要下载的依赖的确来自多个仓库当指定多个仓库时下载一个依赖包会依次从这多个仓库查找并下载

 

虽然maven的settings.xml语法支持多个仓库但localRepository却只能指定一个所以要看下docker是否支持将多个目录volume到同一个容器中的目录即上图中的红线但初步看了docker官网文档并不支持

 

那是否可以用overlay的方式即使可行但overlay时谁在lower谁在upper这个得根据settings.xml中指定的多个仓库的顺序来才行于是得在启pod构建前要解析下这应用的settings.xml稍嫌复杂

 

为解决按仓库隔离.m2且应用依赖多个仓库时的问题我们现在通过对amaven的优化来解决

 

image.png

架构5.0repo_mirror

 

当amaven执行mvn build时当一个依赖包不在本地.m2目录而要下载时会先到repo_mirror中对应的仓库中找如找到则从repo_mirror中对应的仓库中将包直接复制到.m2否则就只能到远程仓库下载下载到.m2后会同时将包复制到repo_mirror中对应的仓库中。

 

通过repo_mirror可以实现同一个node上只会下载一次同一个仓库的同一个文件。

 

当然如果有合适的共享存储多个node共享一个存储服务,那就能解决多个node只下载一次同一个仓库的同一个文件了。

 

a) SNAPSHOT版本号缓存

 

其实在amavenServer的缓存中,除了依赖树,还缓存了SNAPSHOT的版本号。

 

我们的应用会依赖一些snapshot包同时当我们在mvn构建时加上-U就会去检测这些SNAPSHOT的更新而在apache-maven中检测SNAPSHOT需要多次请求maven仓库,会有一些网络开销。

 

现在我们结合maven仓库作了优化,从而让多次请求maven仓库,换成了一次cache服务直接拿到SNAPSHOT的最新版本。

 

image.png 

 

1) 增量

 

增量是与缓存息息相关的,增量的实现就是用缓存。maven的开放性是通过插件机制实现的,每个插件实现具体的功能,是一个函数。当输入不变,则输出不变,即复用输出,而将每次每个函数执行后的输出缓存起来。

 

上面讲的依赖树缓存,也是maven本身(非插件)的一种增量方式。

 

要实现增量的关键是定义好一个函数的输入与输出,即要保证定义好的输入不变时,定义好的输出肯定不变。每个插件自己是清楚输入与输出是什么的,所以插件的增量不是由amaven统一实现,而是amaven提供了一个机制。如一个插件按约定定义好了输入与输出,则amaven在执行前会检测输入是否变化,如没变化,则直接跳过插件的执行,而从缓存中取到输出结果。

 

但其实一个插件的输入与输出要定义清楚并没那么简单,我们拿maven-compiler-plugin来说。maven-compiler-plugin简单地说,它的输入是src/java目录,输出是classes目录。但有些场景即使src/java没变,classes也不能复用。如一个project有二个module:A与B。B中有一个Java文件引用了A的一个Java文件的常量。A修改了一个Java中的一个常量,A会重新compile。但B没修改Java文件,但B也要重新compile。

 

除了常量外,还有一些ABI兼容性的问题也要考虑。module B依赖A,B调用了A中的一个方法fooString[] args,当A将方法签名修改成fooString... args,B不用修改对应的调用foo方法的类,而需要重新编译,否则运行时会报找不到方法。

 

一个module执行一个插件,是否能用增量,不只是考虑自己module的变化情况,还要考虑其它module及直接依赖或间接依赖的变化情况,这会让增量的实现有一定的挑战性。需要不断的校正输入。

 

但增量的效果是明显的,如依赖树缓存与算法的优化能让maven构建从10分钟降到2分钟,那增量则可以将构建耗时从分钟级降到秒级。

 

而gradle与bazel能达到修改一个Java文件,几秒内完成编译,就是增量效果的体现。当然它们也有定义清晰与准确输入的挑战性。

 

2) daemon与分布式

 

daemon是为了进一步达到10秒内构建的实现途径。

 

maven也是Java程序,运行时要将字节码转成机器码,而这转化有时间开销。虽这开销只有几秒时间,但对一个mvn构建只要15秒的应用来说,所占比例也有10%多。为降低这时间开销,可以用JIT直接将maven程序编译成机器码,同时mvn在构建完成后,不退出,常驻进程,当有新构建任务来时,直接调用mvn进程。

 

一般,一个maven应用编译不会超过10分钟,所以,看上去没必要将构建任务拆成子任务,再调度到不同的上执行分布式构建。因为分布式调度有时间开销,这开销可能比直接在本机上编译耗时更大,即得不偿失。

 

所以分布式构建的使用场景是大库。为了简化版本管理,将二进制依赖转成源码依赖,将依赖较密切的源码放在一个代码仓库中,就是大库。当一个大库有成千上万个module时,则非用分布式构建不可了。使用分布式构建,可以将大库几个小时的构建降到几分钟级别。

相关文章
|
2月前
|
设计模式 消息中间件 传感器
Java 设计模式之观察者模式:构建松耦合的事件响应系统
观察者模式是Java中常用的行为型设计模式,用于构建松耦合的事件响应系统。当一个对象状态改变时,所有依赖它的观察者将自动收到通知并更新。该模式通过抽象耦合实现发布-订阅机制,广泛应用于GUI事件处理、消息通知、数据监控等场景,具有良好的可扩展性和维护性。
289 8
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
Java与生成式AI:构建内容生成与创意辅助系统
生成式AI正在重塑内容创作、软件开发和创意设计的方式。本文深入探讨如何在Java生态中构建支持文本、图像、代码等多种生成任务的创意辅助系统。我们将完整展示集成大型生成模型(如GPT、Stable Diffusion)、处理生成任务队列、优化生成结果以及构建企业级生成式AI应用的全流程,为Java开发者提供构建下一代创意辅助系统的完整技术方案。
223 10
|
2月前
|
人工智能 算法 Java
Java与AI驱动区块链:构建智能合约与去中心化AI应用
区块链技术和人工智能的融合正在开创去中心化智能应用的新纪元。本文深入探讨如何使用Java构建AI驱动的区块链应用,涵盖智能合约开发、去中心化AI模型训练与推理、数据隐私保护以及通证经济激励等核心主题。我们将完整展示从区块链基础集成、智能合约编写、AI模型上链到去中心化应用(DApp)开发的全流程,为构建下一代可信、透明的智能去中心化系统提供完整技术方案。
274 3
|
2月前
|
Java 项目管理 Maven
Maven项目管理与构建自动化完全指南
Maven彻底改变了Java项目管理方式,通过POM模型、依赖管理和标准化构建流程,大幅提升开发效率。本文深入解析其核心概念、多模块管理、私服搭建及与Spring Boot、Docker等现代技术栈的集成实践,助力开发者实现高效、规范的项目构建与团队协作。
Maven项目管理与构建自动化完全指南
|
2月前
|
机器学习/深度学习 人工智能 监控
Java与AI模型部署:构建企业级模型服务与生命周期管理平台
随着企业AI模型数量的快速增长,模型部署与生命周期管理成为确保AI应用稳定运行的关键。本文深入探讨如何使用Java生态构建一个企业级的模型服务平台,实现模型的版本控制、A/B测试、灰度发布、监控与回滚。通过集成Spring Boot、Kubernetes、MLflow和监控工具,我们将展示如何构建一个高可用、可扩展的模型服务架构,为大规模AI应用提供坚实的运维基础。
271 0
|
2月前
|
人工智能 Java 物联网
Java与边缘AI:构建离线智能的物联网与移动应用
随着边缘计算和终端设备算力的飞速发展,AI推理正从云端向边缘端迁移。本文深入探讨如何在资源受限的边缘设备上使用Java构建离线智能应用,涵盖从模型优化、推理加速到资源管理的全流程。我们将完整展示在Android设备、嵌入式系统和IoT网关中部署轻量级AI模型的技术方案,为构建真正实时、隐私安全的边缘智能应用提供完整实践指南。
345 3
|
2月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
143 8
|
2月前
|
人工智能 监控 Java
Java与AI智能体:构建自主决策与工具调用的智能系统
随着AI智能体技术的快速发展,构建能够自主理解任务、制定计划并执行复杂操作的智能系统已成为新的技术前沿。本文深入探讨如何在Java生态中构建具备工具调用、记忆管理和自主决策能力的AI智能体系统。我们将完整展示从智能体架构设计、工具生态系统、记忆机制到多智能体协作的全流程,为Java开发者提供构建下一代自主智能系统的完整技术方案。
433 4
|
2月前
|
机器学习/深度学习 分布式计算 Java
Java与图神经网络:构建企业级知识图谱与智能推理系统
图神经网络(GNN)作为处理非欧几里得数据的前沿技术,正成为企业知识管理和智能推理的核心引擎。本文深入探讨如何在Java生态中构建基于GNN的知识图谱系统,涵盖从图数据建模、GNN模型集成、分布式图计算到实时推理的全流程。通过具体的代码实现和架构设计,展示如何将先进的图神经网络技术融入传统Java企业应用,为构建下一代智能决策系统提供完整解决方案。
358 0
|
2月前
|
人工智能 缓存 自然语言处理
Java与多模态AI:构建支持文本、图像和音频的智能应用
随着大模型从单一文本处理向多模态能力演进,现代AI应用需要同时处理文本、图像、音频等多种信息形式。本文深入探讨如何在Java生态中构建支持多模态AI能力的智能应用。我们将完整展示集成视觉模型、语音模型和语言模型的实践方案,涵盖从文件预处理、多模态推理到结果融合的全流程,为Java开发者打开通往下一代多模态AI应用的大门。
358 41

推荐镜像

更多