Spring 启动时长优化是否有必要

2023-08-16 09:22:28 +08:00
 linyimin520812

最近在 reddit 上推广自己的关于 Spring 启动优化小项目,之前也在 v 站推广过:

评论区有个评论者 ta 的意见是没有意义,理由如下:

一开始看到这个评论还挺难过的,毕竟辛苦做的东西,被别人说的一文不值。后面去了解了一下这个开发者说的 GraalVM ,发现确实很强大,编译出的 native 启动速度确实非常的快。

所以我也开始认真的思考这个项目是否真的有意义,这个项目的背景是公司为了降低线上故障时回滚止血时间,要求应用启动时长必须要小于指定的时间,结合一些可以显著提高 Java 启动速度方法无观测不优化的观点实现的,最大的一个优化应用是:将启动时间由原来的将近 6 分钟优化至 3 分钟。

如果没有公司的强推,那还有没有必要这样做 spring 应用启动的优化,就像评论说的直接使用 GraalVM 。个人觉得还是有必要的:

以上就是我能想到的观点,感觉这个评论者是 GraalVM 的忠实粉丝,而且认为这是在发布垃圾消息,所以选择在 v 站想和大家再讨论一下,spring 启动时长的优化是否有必要

7125 次点击
所在节点    程序员
90 条回复
linyimin520812
2023-08-16 15:47:07 +08:00
@weijancc 很多时候依赖了其他团队的二方包,里面的一些初始化操作会比较耗时,应用启动时长会慢慢被拉长
Masoud2023
2023-08-16 15:59:21 +08:00
非要我喷的话,我觉得“线上出现故障回滚的时候,启动速度越快,回滚越快,损失就越小”这个问题就不应该存在,一个正规的发版流程应该对这种事情做一些灰度或者直接从网关层面切换新/旧集群之类的策略来保证不会出现这种问题,如果有这种问题了,解决的应该是整个流程上的问题,而不是 spring 启动速度的问题。

当然了,这个想法我还是很喜欢的,不过 java+spring 这种技术组合感觉就不是那种有启动速度优化空间的组合...
cheng6563
2023-08-16 16:04:29 +08:00
GraalVM 编译出来启动非常快,但编译速度呢?
linyimin520812
2023-08-16 16:10:28 +08:00
@Masoud2023 工作的这段时间也看过一些复盘,线上故障回滚的场景确实存在,还不少
linyimin520812
2023-08-16 16:13:20 +08:00
@Masoud2023 我也非常同意正规发版流程的重要性
moeyui
2023-08-16 16:17:51 +08:00
很有意义,更快的启动速度可以帮助服务更好地伸缩,从而节约成本。现在很多 Java 项目启动速度太慢,动辄几分钟,很难像 Node.js 、Golang 等项目那样使用弹性伸缩,高峰期根本来不及扩容。
GraalVM 确实很快,但它对反射、动态代理有太多限制,特别是老项目很难迁移到 GraalVM 。而且 GraalVM 的编译成本非常高,速度慢还吃资源。
shengchen11
2023-08-16 16:20:34 +08:00
请教一个问题,如果依赖的中间件使用了动态加载类,只能期望中间件主动适配 GraalVM 吗
keshawnvan
2023-08-16 16:23:08 +08:00
启动速度挺重要的,会影响 CICD 的速度,从而降低研发效率。
BeautifulSoap
2023-08-16 16:38:56 +08:00
@aper 我司的一个银行周边项目上了 GraalVM ,而且还上了 serverless ,就那边项目组的说法也没什么大问题
linyimin520812
2023-08-16 16:46:03 +08:00
@BeautifulSoap 这个是新起的项目还是老项目升级的呀?
BeautifulSoap
2023-08-16 16:48:09 +08:00
对了,lz 可以了解一下 aws lambda 提供的 SnapStart 这个功能。
因为 lambda 是 serverless 框架,从冷启动状态开启容器运行服务是常态,所以 lambda 上跑的 java 也会面临严重的启动缓慢的问题。aws 是从另一个完全不同的角度解决了 java 启动慢的问题(官方说快了 10 倍),可以参考。
ahill
2023-08-16 16:56:29 +08:00
因为 spring 本身就是一坨,在一坨上面雕花本身就很难受。但是应该很多场景和公式不得不再一坨屎上雕花
carrymaniac
2023-08-16 17:19:01 +08:00
我们现在为了启动速度,把 cpu 和 memory limit 都拉高了 实际上启动完之后运行又压根用不到那么多 cpu 和 memory 不知道有什么优化的办法
fish267
2023-08-16 17:27:52 +08:00
非常有意义,超长的项目启动简直是浪费生命,你这么做就是 save life 了
xuanbg
2023-08-16 18:00:55 +08:00
3-6 秒应该还可以吧,懒得优化了
linyimin520812
2023-08-16 18:36:52 +08:00
@xuanbg 这个控制的太好了,基本上和空项目启动的时间差不多了
kid1412621
2023-08-16 19:13:07 +08:00
@yazinnnn #9 spring 6 不是支持 aot 吗
ixiaohei
2023-08-16 21:15:09 +08:00
以前看过 spring boot 的源代码:是扫描所有 class 文件,反射查看是否有指定的注解然后注册 bean 配置,jar 包越多扫描的文件就越多,启动就越慢,可以通过限定扫描 class path 范围来缩短扫描范围从而加快启动时间,但 spring boot 自身需要扫描的包本来就多;优化不是很明显,以前项目启动都快 2 分钟;彻底决定要放弃 java 代码配置 bean 的方式,或者禁止扫描和反射 class 方式。

以前使用 java spring 那套比较慢,开发也能忍受了。其实启动快有非常大的优势,后面切到 golang 技术栈上就体会到了。
比如在上云后的以下场景中
场景 1: 快速扩容场,程序启动快可以快速提供服务,减轻总体服务压力从而快速过度到平稳时期;比如在依赖 CPU 自动扩容的情况下,如果在计算周期(一般可能 30 秒或者 1 分钟)下能扩容的实例未及时提供服务,未有效减轻现有服务的压力( CPU ),会继续超量扩容;如果扩容多了后续还会因为平摊到单个的 CPU 下降厉害,继续缩容实例下降,导致波动较长。
场景 2: crash 场景下能快速的恢复服务,特别是集群宕机迁移恢复,一般容易导致全部实例不可用,服务启动越快越好,可以有效减少停止服务时间。
场景 3: 实例较少的情况下优势越明显,停止服务的时间就会越短。很多时候服务因为成本原因,压力不大服务都是 2 台实例,如果 2 台实力同时 crash ,需要恢复的时间越短越好;如果只有一台 crash 。另外一台就处于危险期内(这个实力挂了就真停止服务了),这个时间也是越短越好的。
ixiaohei
2023-08-16 21:20:58 +08:00
java 技术栈上 GraalVM 的 aot 解决启动时间慢有很大的优势,但是国内没有见过大厂分享成熟且大规模的应用的经验。另外 spring 体系下切到 graalvm aot 貌似还有很长的路要走。对于 native 优先的 quarks 框架国内用的就更少了。这块上跟 golang 这个 native 语言还有很大的差距。
bugu1986
2023-08-16 21:22:11 +08:00
如果用在 serverless 中还是有必要的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/965669

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX