Spring Boot 和 Wildfly Swarm 的性能基本对比测试

| May 27, 2016

Wildfly Swarm 1.0.0.CR1 发布

Wildfly-swarm 1.0.0.CR1今天发布了。 http://wildfly-swarm.io/posts/announcement-1-0-0-cr1

Wildfly-swarm是一个基于Wildfly-core的微服务项目,和Wildfly应用服务器共同使用相同的内核组件MSC。我们可以认为它是和SpringBoot类似的项目,拥有相似的架构和开发/构建方法。基础组件对比如下:

  • 注入服务:SpringFramework和 Weld CDI容器
  • Web容器:嵌入式的Tomcat和嵌入式的Undertow
  • Rest数据:SpringMVC和JaxRS实现RestEasy
  • 持久层:均采用JPA和Hibernate作为实现
  • 嵌入式的数据库:HsqlDB和H2数据库
  • 构建:都采用Maven进行构建,可以选用Gradle

JavaEE原来开发应用的步骤是:1.启动应用服务器,2.进行部署。 微服务时代,JavaEE编程方式需要调整来适应。从部署到服务器中改造为直接启动应用进程,内嵌一个web容器。 把所需要的jar和应用代码全部打包到一个jar或者war中,通过

java -jar example.war

的方式来启动服务。

这个项目从启动到现在过去了一年多,如今进入到候选发布版本时期,也意味者整体架构和API不会再有大的变化,功能和性能都已经比较稳定了。

与此同时, SpringBoot毫无疑问是过去的一年中的明星项目,下载量节节升高,越来越多的项目采用SpringBoot来开发。Docker和微服务的各种技术大会上也都能听到开发者热烈讨论和学习。

Wildfly-swarm一直作为SpringBoot的一个潜在对手项目在努力开发中,如今发布了CR版本,我们希望通过简单的性能对比测试来得到一手的数据。

测试方法介绍

我们选用两个项目中现成的有代表性的例子作为测试用例。两个例子的架构基本相同:

  • 内嵌Web容器
  • 使用MVC或者JaxRS来表现Rest文本数据
  • 利用Spring框架或者CDI框架,注入beans
  • 持久层使用JPA,Hibernate 5作为实现
  • 使用嵌入式数据库,启动时加载少量测试数据
  • mvn构建打包好的war,可以直接用java执行

测试机器为

Linux Ubuntu 14.04.3, 8 Core, 8G Mem

Linux useopen-w5 3.16.0-33-generic #44~14.04.1-Ubuntu SMP Fri Mar 13 10:33:29 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

Java虚拟机为Oracle JDK:

java version "1.8.0_74"
Java(TM) SE Runtime Environment (build 1.8.0_74-b02)
Java HotSpot(TM) 64-Bit Server VM (build 25.74-b02, mixed mode)

使用Apache-jmeter来进行简单的性能测试,版本为2.13。

创建一个线程组:十个并发线程,每个运行5000次,每一轮测试运行50000次访问(thread 10, Rarm-up: 1sec, loop count: 5000)

创建一个HTTP Request来访问本地8080 web端口,并建立一个Generate Summary Result来输出测试的结果。

另外启动一个jconsole,挂到服务进程上查看资源的占用情况。

每个项目用例都运行两轮,方法是启动后先跑一次warm-up测试,记录相关数据后,连续跑三轮正常的应用测试。关闭并重启应用服务进程后,再做一遍第二轮的测试。

SpringBoot 测试

获取SpringBoot 1.4.0.M2版本,编译例子/spring-boot/spring-boot-samples/spring-boot-sample-jpa/,在target目录下有 spring-boot-sample-jpa-1.4.0.M2.jar文件,大小26.2M,解压后在三方包目录下有48个jar。

关键的组件版本如下:

  • tomcat-embed 8.0.33
  • spring 4.3.0.RC1
  • Jackson 2.7.3
  • hsqldb 2.3.3
  • hibernate 5.1.0

使用java启动进程,启动时间为 6.0秒 左右。

用浏览器访问http://localhost:8080,得到数据

Title	Body	Tags
Spring Boot	Takes an opinionated view of building production-ready Spring applications.	
Spring Framework	Core support for dependency injection, transaction management, web applications, data access, messaging, testing and more.	
Spring Integration	Extends the Spring programming model to support the well-known Enterprise Integration Patterns.	
Tomcat	Apache Tomcat is an open source software implementation of the Java Servlet and JavaServer Pages technologies.

启动后的堆,活跃线程,加载的类数目分别为:

  • heap: 121M
  • live threads: 19
  • current classes loaded: 8649

使用jmeter压测一边,50000次访问后的两轮的结果为:

R1: Generate Summary Results =  50000 in    18s = 2841.4/s
R2: Generate Summary Results =  50000 in    19s = 2681.3/s 

经过几秒等稳定后,观察jconsole中的系统状态,堆的大小两轮不太一致:

  • heap: 105-212M
  • live threads: 27
  • current classes loaded: 9411

分别记录两轮压测性能数据:

Generate Summary Results =  50000 in   7.3s = 6832.5/s
Generate Summary Results =  50000 in   7.4s = 6721.3/s 
Generate Summary Results =  50000 in   7.5s = 6709.6/s 

Generate Summary Results =  50000 in     8s = 6323.5/s
Generate Summary Results =  50000 in     8s = 6596.3/s 
Generate Summary Results =  50000 in     8s = 6544.5/s

在测试过程中,Heap的变化曲线:

image::http://www.useopen.net/pic/springboot_heap.png[Heap - SpringBoot]

手工GC后

  • heap: 37M
  • live threads: 27
  • current classes loaded: 9407

Wildfly-swarm 测试

获取Wildfly-swarm 1.0.0.CR1版本,编译例子/wildfly-swarm/wildfly-swarm-examples/jpa-jaxrs-cdi/jpa-jaxrs-cdi-war,在target目录下有 example-jpa-jaxrs-cdi-war-swarm.jar文件,大小88.2M,解压后在三方包目录下有325个jar。

不得不说这个包实在是太大了,里面基本包含wildlfy应用服务器的全部组件。具体的分析我会再写一篇分析文章。

关键的组件版本如下:

  • wildfly-core 2.0.12
  • undertow 1.3.15
  • resteasy 3.0.14
  • jackson 2.5.4
  • hibernate 5.0.7
  • weld 2.3.2
  • h2 1.4

使用java启动进程,启动时间为 3.4秒 左右。

用浏览器访问http://localhost:8080,得到数据

[{"id":1,"name":"Penny"},{"id":2,"name":"Sheldon"},{"id":3,"name":"Amy"},{"id":4,"name":"Leonard"},{"id":5,"name":"Bernadette"},{"id":6,"name":"Raj"},{"id":7,"name":"Howard"},{"id":8,"name":"Priya"}]

使用jmeter压测一边,50000次访问后的两轮的结果为:

R1: Generate Summary Results =  50000 in    10s = 5008.0/s
R2: Generate Summary Results =  50000 in    11s = 4754.7/s

经过几秒等稳定后,观察jconsole中的系统状态:

  • heap: 115M
  • live threads: 184
  • current classes loaded: 14114

分别记录两轮压测性能数据:

Generate Summary Results =  50000 in     4s = 13661.2/s 
Generate Summary Results =  50000 in   3.5s = 14476.0/s
Generate Summary Results =  50000 in   3.3s = 14970.1

Generate Summary Results =  50000 in     4s = 13931.5/s 
Generate Summary Results =  50000 in     4s = 13954.8/s
Generate Summary Results =  50000 in     4s = 14064.7/s 

每次测试heap都会明显增加,在测试过程中,Heap的变化曲线:

Heap - WildflySwarm

手工GC后

  • heap: 29M
  • live threads: 185
  • current classes loaded: 14110

总结

SpringBoot和Widfly-swarm都是极为优秀的项目,在微服务时代来临时,它们让Java程序员利用已有的JavaEE编程知识,快捷高效的开发出健壮稳定的应用。

两个项目的启动时间都在几秒种,而且在普通的笔记本上,能用未经过调优的普通应用环境完成每秒上万个服务请求,性能已经很不错了。而且是较为完整的技术栈,包含页面数据,服务和数据库持久等层。

wildfly-swarm作为后来者,表现令人侧目!

  • 启动时间,
  • 热身测试
  • 正式的应用测试

都比SpringBoot差不多快了一倍。直观的比较图形:

Spring VS WildflySwarm

性能优异的原因我只能从架构上先简单猜测下,等进一步研究后再给出具体分析:

  1. wildfly-core内部MSC内核是异步注入容器,性能非常强劲。
  2. undertow的网络层使用XNIO框架,采用和Netty类似的原理,可能比Tomcat的网络层要高效一些?
  3. 不太确认两者分别在web/服务/JPA等层次是否有缓存,以及缓存的策略。因为我们的测试是不变数据,所以不能反应真实应用场景。

需要说明的是Wildfly-swarm应用的打包文件实在是太大,有些范例要超过150M,微服务不“微”。当然,打包中的jar存放在树形目录module中,也许可以利用docker的文件层次堆叠特性来做一个微服务jar公有仓库,这样每个包就可以很小了。

Java应用占用的内存也较大,不过都在可接受范围之内。需要针对具体的应用进行调优。

非常感谢Wildfly-swarm团队带给我们如此优秀的开源项目! Awesome wildfly-swarm!