SpringBoot性能调优
Spring 框架给企业软件开发者提供了常见问题的通⽤解决⽅案,包括那些在未来开发中没有意识到的问题。但是,它构建的 J2EE 项⽬变得越来越臃肿,逐渐被 Spring Boot 所替代。Spring Boot 让我们创建和运⾏项⽬变得更为迅速,现在已经有越来越多的⼈使⽤它。我们已经在⼏个项⽬中使⽤了 Spring Boot ,今天我们就来⼀起讨论⼀下如何改进 Spring Boot 应⽤的性能。
⾸先,从之前我在开发中遇到的⼀个问题说起。在⼀次查看项⽬运⾏⽇志的时候,我偶然发现了⼀个问题,⽇志⾥显⽰这个项⽬总是加载Velocity 模板引擎,但实际上这个项⽬是⼀个没有 web 页⾯的 REST Service 项⽬。于是我花了⼀点时间去寻产⽣这个问题的原因,以及如何改进 Spring Boot 应⽤的性能。在查了相关的资料后,我得出的结论如下:
组件⾃动扫描带来的问题
默认情况下,我们会使⽤ 注解来⾃动获取应⽤的配置信息,但这样也会给应⽤带来⼀些副作⽤。使⽤这个注解后,会触发⾃动配置( )和组件扫描 ( ),这跟使⽤ @Configuration、@EnableAutoConfiguration 和 @ComponentScan 三个注解的作⽤是⼀样的。这样做给开发带来⽅便的同时,也会有三⽅⾯的影响:
1、会导致项⽬启动时间变长。当启动⼀个⼤的应⽤程序,或将做⼤量的集成测试启动应⽤程序时,影响会特别明显。
2、会加载⼀些不需要的多余的实例(beans)。
3、会增加 CPU 消耗。
针对以上三个情况,我们可以移除 @SpringBootApplication 和 @ComponentScan 两个注解来禁⽤组件⾃动扫描,然后在我们需要的bean 上进⾏显式配置:
Java
// 移除 @SpringBootApplication and @ComponentScan, ⽤ @EnableAutoConfiguration 来替代
@Configuration
@EnableAutoConfiguration
public class SampleWebUiApplication {
// ...
// ⽤ @Bean 注解显式配置,以便被 Spring 扫描到
@Bean
public MessageController messageController(MessageRepository messageRepository) {
return new MessageController(messageRepository);
}
如何避免组件⾃动扫描带来的问题
我们在上⾯提到,@SpringBootApplication 注解的作⽤跟 @EnableAutoConfiguration 注解的作⽤是相当的,那就意味着它也能带来上述的三个问题。要避免这些问题,我们就要知道我们需要的组件列表是哪些,可以⽤ -Ddebug 的⽅式来帮助我们明确地定位:
mvn spring-boot:run -Ddebug
…
=========================
AUTO-CONFIGURATION REPORT
=========================
Positive matches:
-----------------
DispatcherServletAutoConfiguration
- @ConditionalOnClass classes found: org.springframework.web.servlet.DispatcherServlet (OnClassCondition)
- found web application StandardServletEnvironment (OnWebApplicationCondition)
...
接着拷贝 Positive matches 中列出的信息:
DispatcherServletAutoConfiguration
EmbeddedServletContainerAutoConfiguration
ErrorMvcAutoConfiguration
HttpEncodingAutoConfiguration
HttpMessageConvertersAutoConfiguration
springboot框架的作用JacksonAutoConfiguration
JmxAutoConfiguration
MultipartAutoConfiguration
ServerPropertiesAutoConfiguration
PropertyPlaceholderAutoConfiguration
ThymeleafAutoConfiguration
WebMvcAutoConfiguration
WebSocketAutoConfiguration
然后来更新项⽬配置,显式地引⼊这些组件,引⼊之后,再运⾏⼀下应⽤确保没有错误发⽣:
Java
@Configuration
@Import({
DispatcherServletAutoConfiguration.class,
EmbeddedServletContainerAutoConfiguration.class,
ErrorMvcAutoConfiguration.class,
HttpEncodingAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
JacksonAutoConfiguration.class,
JmxAutoConfiguration.class,
MultipartAutoConfiguration.class,
ServerPropertiesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ThymeleafAutoConfiguration.class,
WebMvcAutoConfiguration.class,
WebSocketAutoConfiguration.class,
})
public class SampleWebUiApplication {
在上⾯的代码中,我们可以删掉我们不需要的组件信息,来提⾼应⽤的性能,⽐如在我的项⽬中,不需要 JMX 和 WebSocket 功能,我就删掉了它们。删掉之后,再次运⾏项⽬,确保⼀切正常。
将Servlet容器变成Undertow
默认情况下,Spring Boot 使⽤ Tomcat 来作为内嵌的 Servlet 容器。我们可以启动项⽬,然后⽤ VisualVM 或者 JConsole 来查看应⽤所占的内存情况:
以上是我使⽤ Spring Boot 的默认⽅式启动应⽤后,⽤ VisualVM 监控到的内存的占⽤情况:堆内存占⽤ 110M,16 个线程被开启。
可以将 。Undertow 是⼀个采⽤ 开发的灵活的⾼性能 Web 服务器,提供包括阻塞和基于 NIO 的⾮堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。⾸先,从依赖信息⾥移除
Tomcat 配置:
Xml
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
然后添加 Undertow:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
启动项⽬后,⽤ VisualVM 监控到的信息显⽰:堆内存占⽤ 90M,13个线程被开启。
还可以根据实际情况设置jvm参数
参数描述:
-XX:MetaspaceSize=128m:元空间默认⼤⼩
-XX:MaxMetaspaceSize=128m:元空间最⼤⼤⼩
-Xms1024m:堆最⼤⼤⼩
-Xmx1024m:堆默认⼤⼩
-Xmn256m:新⽣代⼤⼩
-Xss256k:栈最⼤深度⼤⼩
-XX:SurvivorRatio=8:新⽣代分区⽐例 8:2
-XX:+UseConcMarkSweepGC:指定使⽤的垃圾收集器,这⾥使⽤CMS收集器
-XX:+PrintGCDetails:打印详细的GC⽇志
java10
最后, 也是最重要的⼀点, java10对java项⽬的启动做了优化, 将jdk版本升级到10以后, java的启动速度明显加快.
在java10, sping boot 2.0的环境下, 相⽐于java8, 快了20%以上(仅以⼀个项⽬做过测试, 数据仅供参考)
总结
这些都是我们在项⽬开发中使⽤到的⼀些优化 Spring Boot 应⽤的⼩技巧,对于⼤的应⽤性能的提⾼还是很明显的。⼤家可以尝试⼀下,然后告诉你的测试结果。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论