当前位置: 首页 > 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…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...