当前位置: 首页 > news >正文

为什么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 可以自动生成这个条目,例如

${settings.localRepository}

   
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的今典应用展开&#xff1a; 下面我用图进行分析&#xff1a; 下面为AC代码&#xff1a; #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代码&#xff1a;点击查看LearnSpringBoot02 点击查看更多的SpringBoot教程 方式一、多个properties文件配置 注意&#xff1a;创建properties文件,命名规则&#xff1a;application-&#xff08;环境名称&#xff09; 示例&#xff1a;application-dev.proper…...

input框中添加一个 X(关闭/清空按钮)

要在输入框&#xff08;<input> 元素&#xff09;中添加一个 X&#xff08;关闭/清空按钮&#xff09;&#xff0c;可以使用 CSS 和 JavaScript 实现。 HTML&#xff1a; <div class"input-container"><input type"text" id"myInput…...

Unity3d Shader篇(三)— 片元半兰伯特着色器解析

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

【vue3学习P5-P10】vue3语法;vue响应式实现

0、vue2和vue3对比 框架版本API方式双向绑定原理domFragmentsTree-Shakingvue2选项式API&#xff08;Options API&#xff09;基于Object.defineProperty&#xff08;监听&#xff09;实现&#xff0c;不能双向绑定对象类型的数据【通过Object.defineProperty里面的set和get做…...

相机图像质量研究(3)图像质量测试介绍

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…...

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自动化版免费设计软件!

今天给大家分享一套完备的电气自动化样例图纸&#xff0c;结构准确、内容清晰&#xff0c;适合初学者入门操作练习。 整套图纸包含图纸目录、原理图、端子列表、连接列表、元件列表、接线图&#xff0c;具有较高的参考价值&#xff0c;请大家点击自行下载文件&#xff01; 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天| 二叉树&#xff1a;理论基础 python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历 python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历 python coding with ChatGPT 打卡第15天| 二叉树&#xff1a;翻转…...

java基础训练题(1)

1.下列代码段中&#xff0c;存在编译错误的语句是(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接口 章末 前言 小伙伴们大家好&#xff0c;上次做了自定义对象属性拷贝&#x…...

闲聊电脑(5)装个 Windows(一)

​夜深人静&#xff0c;万籁俱寂&#xff0c;老郭趴在电脑桌上打盹&#xff0c;桌子上的小黄鸭和桌子旁的冰箱又开始窃窃私语…… 小黄鸭&#xff1a;冰箱大哥&#xff0c;上次说到硬盘分区和格式化&#xff0c;弄完之后&#xff0c;就该装系统了吧&#xff1f; 冰箱&#x…...

Debian系统简介

目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版&#xff…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习

禁止商业或二改转载&#xff0c;仅供自学使用&#xff0c;侵权必究&#xff0c;如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝

目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为&#xff1a;一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...