为什么SpringBoot胖Jar不好
公平地说,我有时会怀念 JavaEE 流行的日子。
当然,当时的情况很复杂,但整个 JavaEE 平台设计合理,符合企业开发的需要。
我可以很轻松地将当时的 JavaEE 应用服务器与现代 Kubernetes 架构进行比较,后者现在也有同样的复杂性、安全性和可维护性问题,甚至可能更糟。而且与 JavaEE 时代不同的是,它没有真正的替代方案。
当时的 JavaEE 和现在的 Kubernetes 都试图(但都失败了)将开发人员从构建可扩展分布式应用的复杂性中解脱出来。
事实上,还有更多的类比,我发现我们现在正在绕一个大圈,先是尝试应用服务器集群,然后是微服务、容器、Kubernetes,现在又回到了模块化单体,而使用类似应用服务器这样允许多个应用/模块并排部署的东西,可能并不是那么疯狂的想法。
考虑到 uber jar 在容器镜像中的效率太低,而将应用程序与其依赖关系分开部署在一个单独的镜像层中更有意义,你就会再次想到单独的应用程序服务器,只不过是在无休止的螺旋式上升的另一个层次上。
JavaEE 规范成功地度过了 Spring 占据主导地位的时代,现在可能会迎来复兴。不知何故,基于 JavaEE 标准的 Quarkus 如今看起来比 Spring 更现代。
欢迎回到新旧 JavaEE 世界。
网友讨论
JEE 背后的许多设计决策都是考虑垂直扩展,容器和微服务有利于水平扩展,不需要应用程序服务器的复杂性。与之互补的是,像 kubernetes 这样的东西使集群充当平台,有可能比大型应用程序服务器规模更大,并且成本更低(许多小型机器与一台大型专用机器)。
==================
如果您想在容器中运行 JVM 应用程序,以获得它能带来的所有好处(可扩展性、声明式方法、自动重启......),那么您绝不会想运行一个完整的应用服务器。
在容器中运行一个完整的应用服务器是没有意义的:它很重,启动速度慢,而且失去了应用服务器的优势。
这不是唯一的原因,因为在容器出现之前,人们就已经开始远离应用服务器了,但这无疑 "扼杀 "了应用服务器。
==================
这其实是个很好的问题,考虑到 Spring Boot 捆绑了Web服务器--我在 Docker 中对捆绑了 Wildfly 服务器的 Jakarta EE 应用程序也做了同样的处理,机制相同,结果相同。
但不管怎么说,Spring Boot 已经过时了,Micronaut、Quarkus 和 GraalVM 的本地可执行文件才是未来的趋势--速度更快,占用内存更少。
=================
应用服务器的最大优点是,你可以用一个 JVM 来管理一切。最大的缺点是只有 1 个 JVM。如果我运行 10 个应用程序,其中一个占用了 JVM 的所有可用内存,那么就会有 10 个应用程序崩溃。而在容器中,尽管内存效率较低,但一个应用程序崩溃也只是该应用程序崩溃。
甚至在容器出现之前,我们公司就遇到过这个问题。我们编写了自己的调度程序和 Java 运行程序,因为这比让大型 tomcat 服务器运行所有程序要简单得多。结果,我们的可靠性大大提高了。
如果 Java 有类似 erlang 的内存空间/进程,那么 EE 模型就会更好用。但是,Java 并不具备这种能力,以后也不会有(太贵了)。
================
可能是因为 Java EE 的最后一次发布是在 2017 年。真实答案为什么你认为它不流行?Jakarta 工作组正在向前推进。你可以在这里看到所有兼容的实现:https://jakarta.ee/compatibility/。很多人正在在 Jakarta EE 上部署应用程序。很抱歉,它在 twitter/tiktok/youtube 上并不流行。
================
不可变容器是一种卓越的部署模式。我们这些多年来一直在管理应用程序/Web 服务器的人再也不想回到那种模式了。先不说容器模式为生产系统管理带来的相对便利,单是开发人员工作效率上的差异就值得我们这样做。
此外,由于部署单元是容器,因此不需要胖 jar。我个人更喜欢使用 Quarkus 的瘦 jar。
在你的容器中,你要么需要一个内嵌有 servlet 容器的胖jar,要么需要一个预部署了应用程序的 servlet 容器。
人们通常会选择带有嵌入式 servlet 容器的 胖jar。
胖 jar 只是一个包含所有依赖项的 jar:当你把应用程序从一个地方复制到另一个地方,或者分发你的应用程序以便在其他地方运行时,它非常方便。
在容器化的世界里,你分发的就是一个容器:在容器中,如果你的应用程序是一个单独的 jar,而它的依赖项在文件系统的其他地方,或者它们作为胖 jar 的一部分包含在 jar 中,那么这并不重要。
我的意思是,如果你要分发一个容器,就真的不需要像 Spring Boot 那样将应用程序及其依赖项打包在一个单一的 jar 中。
Jib 在某种程度上就是这么做的,它不是创建一个胖Jar,而是创建一个多层容器,在不同的层上有不同类别的依赖关系。一个额外的步骤/层可以是网络服务器。
对于这样的应用来说,Jib 就显得有些矫枉过正了。在 Spring Boot 中,spring-boot-thin-launcher 可以生成应用程序的精简 jar 发行版。您必须在容器创建前(或作为创建过程的一部分)将其配置为下载依赖项。否则,它会在您启动容器时下载您的依赖项,这不是好的做法。
Quarkus 默认生成 fast-jar(瘦 jar):
- 它使用自定义类加载器加载依赖项,速度比系统类加载器快很多。
- 任何生成瘦 jar 的构建都会将所有依赖项和构建的应用程序 jar 复制到 "target "下的文件夹中。然后,你只需在构建容器时复制该文件夹即可。
这种瘦 jar方式为什么比胖Jar好?
如果你在编译/编辑/运行循环中进行 docker 部署,它就会非常有用。或者,当你在更高的环境中四处奔波,试图让东西正常工作时,它也非常有用。
如果把复制 jar 分成两个 COPY 命令:
-
第一个复制所有依赖库
-
第二个复制应用逻辑 jar,
这意味着 docker 会创建两个独立的层。依赖库很少变化,所以 docker 只需要在极少数情况下推送这一层。
对于有大量依赖库的大型项目来说,在网络连接速度较慢的情况下(我在家里工作,网络连接速度很差),大多数情况下,推送操作可以从 2-3 分钟缩短到小于 30 秒。
它还能节省推送到的 docker 仓库的空间。所有使用相同依赖关系的镜像都指向同一层。
因此,在容器环境中,生成胖 jar 是不必要的。瘦 jar 格式是自然的 Java 方式。
生成廋Jar的小技巧
很少有人知道 MANIFEST.MF classpath 条目。Maven 可以自动生成这个条目,例如
org.apache.maven.plugins
maven-jar-plugin
default-jar
true
${exec.mainClass}
${exec.classpathPrefix}
repository
false
这将使 JAR 可以运行,前提是类路径条目是相对或绝对的。
这比 Spring Boot 的 fatjar 启动时间要快得多
基本上,你在开发过程中的运行方式已经发生了变化。由于无需为开发和 CI 打包一个巨大的 jar,构建时间大大缩短。
至于 docker,你可以先构建,然后复制依赖项,更改 classpathprefix 并使用依赖项插件,或者使用 maven 构建插件和 Transitive Deps(~/.m2/),接受一个稍大的镜像......例如,你可以用本地 maven 仓库装运一个容器。
相关文章:
为什么SpringBoot胖Jar不好
公平地说,我有时会怀念 JavaEE 流行的日子。 当然,当时的情况很复杂,但整个 JavaEE 平台设计合理,符合企业开发的需要。 我可以很轻松地将当时的 JavaEE 应用服务器与现代 Kubernetes 架构进行比较,后者现在也有同样…...
Java学习笔记2024/2/6
练习三:验证码 需求: 定义方法实现随机产生一个5位的验证码 验证码格式: 长度为5 前四位是大写字母或者小写字母 最后一位是数字 package com.angus.comprehensiveExercise; import java.util.Random; public class test3 {publ…...
2024 高级前端面试题之 前端安全模块 「精选篇」
该内容主要整理关于 前端安全模块 的相关面试题,其他内容面试题请移步至 「最新最全的前端面试题集锦」 查看。 前端安全模块精选篇 1. 代码注入XSS如何攻击如何防御cookie 如何防范 XSS 攻击 2. 跨站请求伪造CSRF3. 浏览器同源策略 SOP4. 跨域资源共享 CORS5. 密码…...

SpringBoot Security安全认证框架初始化流程认证流程之源码分析
SpringBoot Security安全认证框架初始化流程&认证流程之源码分析 以RuoYi-Vue前后端分离版本为例分析SpringBoot Security安全认证框架初始化流程&认证流程的源码分析 目录 SpringBoot Security安全认证框架初始化流程&认证流程之源码分析一、SpringBoot Security安…...

2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测
2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测 目录 2024美赛预测算法 | 回归预测 | Matlab基于RIME-LSSVM霜冰算法优化最小二乘支持向量机的数据多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效…...
test1
1...

远程主机可能不符合 glibc 和 libstdc++ Vs Code 服务器的先决条件
vscode连接远程主机报错,原因官方已经公布过了,需要远程主机 glibc>2.28,所以Ubuntu18及以下版本没法再远程连接了,其他Linux系统执行ldd --version查看glibc版本自行判断。 解决方案建议: 不要再想升级glibc了 问题…...

备战蓝桥杯---数据结构与STL应用(进阶2)
本文将主要围绕有关map的今典应用展开: 下面我用图进行分析: 下面为AC代码: #include<bits/stdc.h> using namespace std; struct Point {int x,y;bool operator < (const Point & r) const {return x < r.x || ( x r.x &a…...

SpringBoot:多环境配置
多环境配置demo代码:点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 方式一、多个properties文件配置 注意:创建properties文件,命名规则:application-(环境名称) 示例:application-dev.proper…...
input框中添加一个 X(关闭/清空按钮)
要在输入框(<input> 元素)中添加一个 X(关闭/清空按钮),可以使用 CSS 和 JavaScript 实现。 HTML: <div class"input-container"><input type"text" id"myInput…...

Unity3d Shader篇(三)— 片元半兰伯特着色器解析
文章目录 前言一、片元半兰伯特着色器是什么?1. 片元漫反射着色器的工作原理2. 片元半兰伯特着色器的优缺点优点:缺点: 3. 公式 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数…...

【vue3学习P5-P10】vue3语法;vue响应式实现
0、vue2和vue3对比 框架版本API方式双向绑定原理domFragmentsTree-Shakingvue2选项式API(Options API)基于Object.defineProperty(监听)实现,不能双向绑定对象类型的数据【通过Object.defineProperty里面的set和get做…...

相机图像质量研究(3)图像质量测试介绍
系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结:光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结:光学结构对成…...
PaddleDetection学习5——使用Paddle-Lite在 Android 上实现实时的人脸检测(C++)
使用Paddle-Lite在 Android 上实现实时的人脸检测 1 环境准备2. 部署步骤2.1 下载Paddle-Lite-Demo2.2 运行face_detection_demo项目3 使用Opencv对后处理进行优化4 开启手机摄像头进行人脸检测1 环境准备 参考前一篇在 Android 上使用Paddle-Lite实现实时的目标检测功能 2. …...

全套电气自动化样例图纸分享,使用SuperWorks自动化版免费设计软件!
今天给大家分享一套完备的电气自动化样例图纸,结构准确、内容清晰,适合初学者入门操作练习。 整套图纸包含图纸目录、原理图、端子列表、连接列表、元件列表、接线图,具有较高的参考价值,请大家点击自行下载文件! 1e8…...

带你实现用自己域名打开Tomcat
文章目录 Tomcat1.1、Tomcat 下载1.2、Tomcat 文件图解1.3、 启动或关闭 Tomcat1.3.1、 启动1.3.2、 关闭程序2.1、 修改端口号2.2、修改主机名称Tomcat 1.1、Tomcat 下载 首先去Tomcat 官网下载找到我们需要下载的版本 1.2、To...

python coding with ChatGPT 打卡第18天| 二叉树:从中序与后序遍历序列构造二叉树、最大二叉树
相关推荐 python coding with ChatGPT 打卡第12天| 二叉树:理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树:翻转…...
java基础训练题(1)
1.下列代码段中,存在编译错误的语句是(B C D) byte b1 1,b2 2,b3,b6,b8; final byte b4 4,b5 6,b7; b3 (b1 b2);/*语句1*/ b6 b4 b5 ; /*语句2*/ b8 (b1 b4);/*语句3*/ b7 (b2 b5);/*语句4*/ System.out.println(b3 b6);A: 语句2 B: 语句1 C: 语句3…...

【自定义序列化器】⭐️通过继承JsonSerializer和实现WebMvcConfigurer类完成自定义序列化
目录 前言 解决方案 具体实现 一、自定义序列化器 二、两种方式指定作用域 1、注解 JsonSerialize() 2、实现自定义全局配置 WebMvcConfigurer 三、拓展 WebMvcConfigurer接口 章末 前言 小伙伴们大家好,上次做了自定义对象属性拷贝&#x…...

闲聊电脑(5)装个 Windows(一)
夜深人静,万籁俱寂,老郭趴在电脑桌上打盹,桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭:冰箱大哥,上次说到硬盘分区和格式化,弄完之后,就该装系统了吧? 冰箱&#x…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地
借阿里云中企出海大会的东风,以**「云启出海,智联未来|打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办,现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
工业自动化时代的精准装配革新:迁移科技3D视觉系统如何重塑机器人定位装配
AI3D视觉的工业赋能者 迁移科技成立于2017年,作为行业领先的3D工业相机及视觉系统供应商,累计完成数亿元融资。其核心技术覆盖硬件设计、算法优化及软件集成,通过稳定、易用、高回报的AI3D视觉系统,为汽车、新能源、金属制造等行…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...