内容简介:原文链接:至今,Java仍旧是用来构建web应用的最流行编程语言之一 —— 但是它不得不面对诸如Go,Python,和TypeScript等新语言的严峻挑战。在Java世界里,Spring框架早已成为微服务开发的事实标准。通过使用诸如Spring Boot和Spring Data这样的库,Spring框架变得简单易用,并且大部分情况下,开发过程高效、无痛点。
原文链接: https://medium.com/better-prog ... 78e58
至今,Java仍旧是用来构建web应用的最流行编程语言之一 —— 但是它不得不面对诸如Go,Python,和TypeScript等新语言的严峻挑战。
在 Java 世界里,Spring框架早已成为微服务开发的事实标准。通过使用诸如Spring Boot和Spring Data这样的库,Spring框架变得简单易用,并且大部分情况下,开发过程高效、无痛点。
然而,最近几年一些新框架不断涌现,声称可以降低Java应用的启动时间和内存占用。我最近一直在用Java去设计大型的微服务架构应用,在做设计之前,我查了哪些Java框架最合适微服务架构。
我主要关注在框架带来的易用性和资源管理。
Spring虽然是Java平台最流行的框架,但是从来没有人说它是最好的框架。在资源管理这方面,尤其是单进程所需要的性能开销这块,Spring差强人意。在应用服务器开发的旧时代,这不是一个大问题,因为进程实例数量不多。然而,随着微服务架构的崛起,我们会有大量的进程,这就使得Sring的这个问题更加突出 —— Christian Lusardi最近就这么说:
”我发现就算一个简单的Java应用,要是用了Spring Boot,那么至少需要1GB的内存才能把它运行起来。要是开发一个中间件,这样的开销还可以接受,但是对于微服务架构来说,太糟糕了!”
可选框架
Spring
Spring是在2003年面世的,以应对旧时代Java企业级开发的复杂性。Spring以依赖注入和面向切面编程为核心,演进成一个易用的web应用开发框架。Spring有着非常多的文档,广泛的使用率和数不清的库,让开发者高效的创建和维护应用程序,并且提供了扁平的学习曲线。
Spring通过反射在运行期间执行依赖注入。当一个Spring applicaiton启动时,在类路径(classpath)中,被标记的类(annotated classes)会被扫描到,由此,具体的类对象被实例化和被连接。
虽然这能提升应用程序的弹性,但是也使得应用程序的启动时间变慢,并且内存开销变大。同时,这个机制使得迁移到GraalVM变得非常困难,因为GraalVM不支持反射。
Micronaut
Micronaut是一个现代化的微服务架构框架,由Grails框架的作者在2018年创造。
它提供了所有必要的 工具 来创造功能全面的微服务应用。同时,它的目标是赋予应用程序快速的启动时间和更低的内存开销。这一切都发生在编译期间而非运行时,使用了Java annotation处理器执行依赖注入,创建面向切面代理,配置应用程序。
Micronaut的许多API从Spring和Grails中获得灵感。这样的设计快速吸引了新开发者的注意。Micronaut提供了很多的模块,诸如Micronaut HTTP,data,security,和连接其他技术的连接器。然而,就成熟度而言,Micronaut的这些库要落后于Spring里对应的库。
Quarkus
Quarkus,在2019年由红帽创造,是一个Kubernetes原生的Java框架。它依托于MicroProfile,Vert.x,Netty和Hibernate。
Quarkus的目标是让Java在容器编排环境中有着更快的启动速度,更低的内存开销和近乎瞬间的扩容伸缩能力,并期望让Java在Kubernetes环境能成为一个主导平台。为达到此目的,Quarkus通过自定义Maven插件在编译期间尽可能地做更多的工作。
Quarkus使用了大量已存在的标准技术,同时对扩展开放。然而这个项目是一年前才开始的,这些扩展的成熟度和兼容性还不明确,很有可能在将来随着平台的成长发生改变。
Helidon MicroProfile
MicroProfile项目始于2016年,那时候大家,对于Oracle会在Java企业级开发这块持续发力,觉得前途未卜。
像它的先驱JEE,MicroProfile只是一份规范,可以被具体架构来实现。
随后,许多具体的实现出现在大家面前,其中最著名的是Payara Micro和Helidon MP。Payara是一种起源于GlassFish的Jakarta企业级服务器,也是MicroProfile一个实现。Helidon则是一个运行时,由Oracle公司在2018年发起,并提供了对于MicroProfile规范的实现。
虽然它们都来自于JEE,并且MicroProfile规范文档成熟与完善,但是缺少了针对其他现代技术的连接器或是一些必要的库来替代Spring Data和Spring Security。
MicroProfile的未来是不明朗的,与它同在Eclipse基金会的另一个项目Jakarta EE,也刚刚开始发展起来。在未来,两者很有可能会合并,—— 至少紧密关联。
框架的比较
为了对上面提及过的框架进行比较,对每一个框架,我都创建了一个简单的应用程序,程序由REST接口和数据库连接器组成(译:JDBC,JPA,Spring Data)。REST接口对objects做增删改查操作,数据库连接器则把这些objects存入数据库中。
如果一个框架支持多种方式接入数据库,我会一一实现,然后对这些应用程序做性能作比较。
我把这些应用跑在OpenJDK Docker镜像里。如果某个框架支持对原生GraalVM镜像生成,我也会把这些拿来作比较。你也可以看下我的另一篇文章来获得更多关于GraalVM的资讯
这些源码你可以在GitHub上找到,地址是 https://github.com/lizzyTheLiz ... mpare 。
我主要从这几个关键点来比较这些应用程序的性能
- 有多容易去实现这些程序样例?为了能够实现这些框架,我不得不去查看相关文档,并同时在stack overflow这类的平台上去寻找相关信息。
- 要编译一个程序要花多久的时间?我测量了执行一次程序构建所需要的时间,这包含了 Docker 镜像生成时间。至于GraalVM这类,则包含了生成原生GraalVM镜像所花的时间。
-
启动一个应用程序要花多少时间?我测量了应用程序在敲下
docker up
命令之后,与它第一次能够正确响应HTTP请球之前的所需要的时间。同时我也比较了程序启在闲置状态下的内存占用。 - 应用程序在高负载状态下能够处理多少请求?我使用了JMeter来做压力测试,其中有25%的请求来执行程序的写操作,另外的75%请求来做数据库读操作。在程序达到高负载的状态,测量它的内存占用。
我在谷歌云上面完成了所有的测试。虚拟机采用了四核的intel Haswell架构CPU和15GB的内存。系统则是Ubuntu 19.01。
所有的测试都重复都做了多次,以避免干扰因素。你可以在 https://github.com/lizzyTheLiz ... mpare ,找到这些脚本和原始数据。
结论
程序开发的易用性
由于之前我已对Spring Boot有一些使用经验,所以这方面的比较,有一点点的不公平。然而,当你查看了Spring的文档,相关信息与例子,Spring是目前为止最容易上手的框架。
Micronaut的文档也做得很棒,它有着与Spring和Grail类似的API,因此,对于用过Spring的开发者来说也是非常容易上手的。
Quarkus的学习曲线更陡峭一些,我认为,相较于Spring与Micronaut,Quarkus的API和库缺乏成熟度,尤其数据库连接方面,易用性比较糟糕。
Helidon在易用性方面是最糟糕的,因为我花了非常大的努力才使得应用程序跑起来。
编译
所有框架只要是使用了OpenJDK,那么编译时间是差不多的,在6.98秒(使用JDBC的Spring应用程序)到10.7秒(使用Quarkus的应用程序)之间。
而原生GraalVM镜像生成的时间开销非常大,在231.2秒(使用JDBC的Micronaut应用程序)到351.7秒(使用JPA的Micronaut应用程序)之间。从开发过程来说,这使得原生GraalVM镜像变得基本无意义,因为编译一个简单的应用程序需要等待4分钟,这是很过分的事。
启动
使用了Spring Data的Spring Boot应用程序平均花费8.16秒来启动。当去除了JPA和Spring Data,这个时间降到了5.8秒。
这里,Micronaut(使用JPA时,花费5.08秒启动,使用JDBC时,花费3.8秒)和Quarkus(花费5.7秒启动)都达到了他们的承诺,可以更快的速度启动应用程序。
只有Helidon MP比Spring 启动速度更慢 —— 平均要8.27秒。
GraalVM,在启动方面,表现最好,启动时间分别是1.39秒(Quarkus应用程序)和1.46秒(使用了JDBC的Micronaut应用程序),远远快于基于OpenJDK的那些实现。
程序启动后的内存使用非常相似。Spring在使用了Spring Data的情况下占用420MB的内存,在使用了JDBC的情况下占用261MB内存
Micronaut在使用了JPA的情况下,占用262MB的内存,在使用了JDBC的情况下占用178MB的内存
Quarkus表现得更好一些,内存开销在197MB。Helidon MP则与Spring Boot类似,内存开销在414MB
高负载
在高负载情况下,Spring Boot表现相当的好,在使用了Spring Data情况下,每秒能够处理342个请求,内存开销是581MB,在使用了JDBC情况下每秒能够处理216个请求,内存开销是484MB。毫无疑问地是,Helidon在高负载状态下表现最糟糕,在高负载情况下,内存开销超过1GB,处理请求只有每秒175个。
其他的框架在高负载情况下,在400请求/秒(使用了原生GraalVM镜像的Quarkus应用程序)到197请求/秒(跑在OpenJDK上的Quarkus应用程序)之间。Micronaut相关的实现也在这个数值之间,当Micronaut搭配JDBC时,每秒处理能力要比Micronaut搭配JPA时要稍微好一些。当Micronaut搭配原生GraalVM镜像时要比Micronaut搭配OpenJDK时要好一些。
就内存使用角度而言,Quarkus搭配OpenJDK,出奇的好,内存开销仅要255MB,这要远远低于Quarkus搭配原生GraalVM镜像的时候,Quarkus搭配原生GraalVM镜像时,平均开销在368MB。
总结
相较于Spring和MicroProfile这样现有的老框架,Micronaut和Quarkus这类的新框架,有着更快的启动速度和更低的内存占用。
但是这些优势是有条件的,仅当程序在空闲状态和低负载状态下才成立,当程序用了原生GraalVM镜像时,这样的优势可以更加突出。
但是在高负载情况下,这些优势就不明显了,即使是用了原生GraalVM镜像。
目前为止,我认为,Spring仍旧是拥有着最好的开发体验,最合适于微服务应用的Java框架,即使它在启动速度方面表现糟糕。
让我感到惊讶的是,使用Hibernate/JPA/Spring Data,会给程序带来巨大的开销,即使是一个非常简单的程序,在使用了这些库后,对内存开销和每秒请求率影响巨大。在此,我特别喜欢Micronaut Data的解决方案,它自动生成相应代码,而不再需要JPA。这个功能真应该加到Spring Data里去啊。
原生GraalVM镜像可以得程序在启动速度方面变得非常的快,内存效率也不错。但是当高负载情况下,就体现不出巨大的优势了。
同时,原生GraalVM镜像也带来了额外的痛点,使得编译时间大大增加,这就让这门技术,仅在要求程序快速
启动的场景下,才有意义——比如说无服务架构(serverless)或者要求快速扩容伸缩的场景。在其他场景下,投入远大于回报。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 五大 JAVA Web 框架的优缺点对比,Spring MVC 领先
- 总结:优缺点及使用场景
- Python IDE 优缺点列表
- 几种编程语言的优缺点
- Kotlin语言的优缺点及建议
- MVP 与 MVVM 优缺点总结
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
互联网产品运营:产品经理的10堂精英课
丁华、聂嵘海、王晶 / 电子工业出版社 / 2017-5 / 59
《互联网产品运营:产品经理的10堂精英课》共有10章,前9章分别从互联网产品运营的9个点入手,最后一章辅以案例,分析当下市场热门产品的运营模式。 第1章点明在运营产品之前需要经过缜密的策划,这样才能有明确的运营方向;第2章讲述产品运营的定位,有了准确的定位,运营才不会走偏;第3章描述用户运营,用户是一款产品的根本,没有用户,产品就是死的;第4章讲述内容运营的技巧,产品内容要怎么运营才能受到用......一起来看看 《互联网产品运营:产品经理的10堂精英课》 这本书的介绍吧!